HEAD ======= >>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
# Always print this out before your assignment
sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggridges_0.5.3 glmnetUtils_1.1.8 glmnet_4.1-2 Matrix_1.3-4 scales_1.1.1
[6] tidyquant_1.0.3 quantmod_0.4.18 TTR_0.24.2 PerformanceAnalytics_2.0.4 xts_0.12.1
[11] zoo_1.8-9 plotly_4.9.4.1 viridis_0.6.2 viridisLite_0.4.0 pastecs_1.3.21
[16] kableExtra_1.3.4 lubridate_1.7.10 rsample_0.1.0 ggthemes_4.2.4 ggrepel_0.9.1
[21] here_1.0.1 fs_1.5.0 forcats_0.5.1 stringr_1.4.0 dplyr_1.0.7
[26] purrr_0.3.4 readr_2.0.1 tidyr_1.1.3 tibble_3.1.4 ggplot2_3.3.5
[31] tidyverse_1.3.1 knitr_1.34
loaded via a namespace (and not attached):
[1] colorspace_2.0-2 ellipsis_0.3.2 rprojroot_2.0.2 rstudioapi_0.13 listenv_0.8.0 furrr_0.2.3 farver_2.1.0
[8] fansi_0.5.0 xml2_1.3.2 splines_4.1.1 codetools_0.2-18 jsonlite_1.7.2 broom_0.7.9 dbplyr_2.1.1
[15] compiler_4.1.1 httr_1.4.2 backports_1.2.1 assertthat_0.2.1 fastmap_1.1.0 lazyeval_0.2.2 cli_3.0.1
[22] htmltools_0.5.2 tools_4.1.1 gtable_0.3.0 glue_1.4.2 Rcpp_1.0.7 cellranger_1.1.0 jquerylib_0.1.4
[29] vctrs_0.3.8 svglite_2.0.0 iterators_1.0.13 crosstalk_1.1.1 xfun_0.26 globals_0.14.0 rvest_1.0.1
[36] lifecycle_1.0.0 pacman_0.5.1 future_1.22.1 hms_1.1.0 parallel_4.1.1 yaml_2.2.1 curl_4.3.2
[43] gridExtra_2.3 sass_0.4.0 stringi_1.7.4 highr_0.9 foreach_1.5.1 boot_1.3-28 shape_1.4.6
[50] rlang_0.4.11 pkgconfig_2.0.3 systemfonts_1.0.3 evaluate_0.14 lattice_0.20-44 htmlwidgets_1.5.4 labeling_0.4.2
[57] tidyselect_1.1.1 parallelly_1.28.1 plyr_1.8.6 magrittr_2.0.1 R6_2.5.1 generics_0.1.0 DBI_1.1.1
[64] pillar_1.6.2 haven_2.4.3 withr_2.4.2 survival_3.2-11 modelr_0.1.8 crayon_1.4.1 Quandl_2.11.0
[71] utf8_1.2.2 tzdb_0.1.2 rmarkdown_2.11 grid_4.1.1 readxl_1.3.1 data.table_1.14.0 reprex_2.0.1
[78] digest_0.6.27 webshot_0.5.2 munsell_0.5.0 bslib_0.3.0 quadprog_1.5-8
getwd()
[1] "C:/BUS_696/final_project/BROCODE_Final_Project"
# load all your libraries in this chunk
library('tidyverse')
<<<<<<< HEAD
-- Attaching packages --------------------------------------------------------------------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5 v purrr 0.3.4
v tibble 3.1.4 v dplyr 1.0.7
v tidyr 1.1.3 v forcats 0.5.1
v readr 2.0.1
-- Conflicts ------------------------------------------------------------------------------------------------------ tidyverse_conflicts() --
=======
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ───────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5 ✓ purrr 0.3.4
✓ tibble 3.1.6 ✓ dplyr 1.0.7
✓ tidyr 1.1.4 ✓ stringr 1.4.0
✓ readr 2.1.0 ✓ forcats 0.5.1
── Conflicts ──────────────────────────────── tidyverse_conflicts() ──
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
library("fs")
library('here')
<<<<<<< HEAD
here() starts at C:/BUS_696
=======
here() starts at /Users/ryanradcliff/Documents/BUS696
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
library('dplyr')
library('tidyverse')
library('ggplot2')
library('ggrepel')
library('ggthemes')
library('forcats')
library('rsample')
library('lubridate')
Attaching package: ‘lubridate’
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
library('ggthemes')
library('kableExtra')
Attaching package: ‘kableExtra’
The following object is masked from ‘package:dplyr’:
group_rows
library('pastecs')
Attaching package: ‘pastecs’
The following objects are masked from ‘package:dplyr’:
first, last
The following object is masked from ‘package:tidyr’:
extract
library('viridis')
Loading required package: viridisLite
library('plotly')
<<<<<<< HEAD
=======
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library('tidyquant')
<<<<<<< HEAD
=======
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Loading required package: PerformanceAnalytics
Loading required package: xts
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
Attaching package: ‘xts’
The following objects are masked from ‘package:pastecs’:
first, last
The following objects are masked from ‘package:dplyr’:
first, last
Attaching package: ‘PerformanceAnalytics’
The following object is masked from ‘package:graphics’:
legend
Loading required package: quantmod
Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
<<<<<<< HEAD
== Need to Learn tidyquant? ================================================================================================================
=======
══ Need to Learn tidyquant? ══════════════════════════════════════════
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Business Science offers a 1-hour course - Learning Lab #9: Performance Analysis & Portfolio Optimization with tidyquant!
</> Learn more at: https://university.business-science.io/p/learning-labs-pro </>
library('scales')
Attaching package: ‘scales’
The following object is masked from ‘package:viridis’:
<<<<<<< HEAD
viridis_pal
The following object is masked from ‘package:purrr’:
discard
The following object is masked from ‘package:readr’:
=======
viridis_pal
The following object is masked from ‘package:purrr’:
discard
The following object is masked from ‘package:readr’:
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
col_factor
# note, do not run install.packages() inside a code chunk. install them in the console outside of a code chunk.
Part 1 - Final Project Cleaning and Summary Statistics
1a) Loading data
#Reading the data in and doing minor initial cleaning in the function call
#Reproducible data analysis should avoid all automatic string to factor conversions.
#strip.white removes white space
#na.strings is a substitution so all that have "" will = na
data <- read.csv(here::here("final_project", "donor_data.csv"),
stringsAsFactors = FALSE,
strip.white = TRUE,
na.strings = "")
1b) Fixing the wonky DOB & Data cleanup
#(Birthdate and Age, ID as a number)adding DOB (Age/Spouse Age) in years columns and adding two fields for assignment and number of children
dataclean <- data %>%
mutate(Birthdate = ifelse(Birthdate == "0001-01-01", NA, Birthdate)) %>%
mutate(Birthdate = mdy(Birthdate)) %>%
mutate(Age = as.numeric(floor(interval(start= Birthdate, end=Sys.Date())/duration(n=1, unit="years")))) %>%
mutate(Spouse.Birthdate = ifelse(Spouse.Birthdate == "0001-01-01", NA, Spouse.Birthdate)) %>%
mutate(Spouse.Birthdate = mdy(Spouse.Birthdate)) %>%
mutate(Spouse.Age = as.numeric(floor(interval(start= Spouse.Birthdate,
end=Sys.Date())/duration(n=1, unit="years")))) %>%
mutate(ID = as.numeric(ID)) %>%
mutate(Assignment_flag = ifelse(is.na(Assignment.Number), 0,1)) %>%
mutate( No_of_Children = ifelse(is.na(Child.1.ID),0,
ifelse(is.na(Child.2.ID),1,2)))
#conferral dates
dataclean <- dataclean %>%
mutate(Conferral.Date.1 = ifelse(Conferral.Date.1 == "0001-01-01", NA, Conferral.Date.1)) %>%
mutate(Conferral.Date.1 = mdy(Conferral.Date.1)) %>%
mutate(Conferral.Date.1.Age = as.numeric(floor(interval(start= Conferral.Date.1, end=Sys.Date())/duration(n=1, unit="years")))) %>%
mutate(Conferral.Date.2 = ifelse(Conferral.Date.2 == "0001-01-01", NA, Conferral.Date.2)) %>%
mutate(Conferral.Date.2 = mdy(Conferral.Date.2)) %>%
mutate(Conferral.Date.2.Age = as.numeric(floor(interval(start= Conferral.Date.2, end=Sys.Date())/duration(n=1, unit="years")))) %>%
mutate(Last.Contact.By.Anyone = ifelse(Last.Contact.By.Anyone == "0001-01-01", NA, Last.Contact.By.Anyone)) %>%
mutate(Last.Contact.By.Anyone = mdy(Last.Contact.By.Anyone)) %>%
mutate(Last.Contact.Age = as.numeric(floor(interval(start= Last.Contact.By.Anyone, end=Sys.Date())/duration(n=1, unit="years")))) %>%
mutate(HH.First.Gift.Date = ifelse(HH.First.Gift.Date == "0001-01-01", NA, HH.First.Gift.Date)) %>%
mutate(HH.First.Gift.Date = mdy(HH.First.Gift.Date)) %>%
mutate(HH.First.Gift.Age = as.numeric(floor(interval(start= HH.First.Gift.Date, end=Sys.Date())/duration(n=1, unit="years"))))
#major gift
dataclean <-
dataclean %>%
mutate(major_gifter = ifelse(Lifetime.Giving > 50000, 1,0) %>% factor(., levels = c("0","1")))
#splitting up the age into ranges and creating category for easy visualization
dataclean <- dataclean %>%
mutate(age_range =
ifelse(Age %in% 10:19, "10 < 20 years old",
ifelse(Age %in% 20:29, "20 < 30 years old",
ifelse(Age %in% 30:39, "30 < 40 years old",
ifelse(Age %in% 40:49, "40 < 50 years old",
ifelse(Age %in% 50:59, "50 < 60 years old",
ifelse(Age %in% 60:69, "60 < 70 years old",
ifelse(Age %in% 70:79, "70 < 80 years old",
ifelse(Age %in% 80:89, "80 < 90 years old",
ifelse(Age %in% 90:120, "90+ years old",
NA))))))))))
#seeing what we have
table(dataclean$age_range)
<<<<<<< HEAD
10 < 20 years old 20 < 30 years old 30 < 40 years old 40 < 50 years old 50 < 60 years old 60 < 70 years old 70 < 80 years old
3985 24558 21037 16851 20755 18257 12246
80 < 90 years old 90+ years old
5984 6633
=======
10 < 20 years old 20 < 30 years old 30 < 40 years old
3990 24560 21034
40 < 50 years old 50 < 60 years old 60 < 70 years old
16857 20748 18258
70 < 80 years old 80 < 90 years old 90+ years old
12242 5986 6632
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
#50-60 is the most common age range
#creating a region column using the county data and the OMB MSA (Metropolitan Statistical Area) definitions
dataclean <- dataclean %>%
mutate(region =
ifelse(County == "San Luis Obispo" & State == "CA", "So Cal",
ifelse(County == "Kern" & State == "CA", "So Cal",
ifelse(County == "San Bernardino" & State == "CA", "So Cal",
ifelse(County == "Santa Barbara" & State == "CA", "So Cal",
ifelse(County == "Ventura" & State == "CA", "So Cal",
ifelse(County == "Los Angeles" & State == "CA", "So Cal",
ifelse(County == "Orange" & State == "CA", "So Cal",
ifelse(County == "Riverside" & State == "CA", "So Cal",
ifelse(County == "San Diego" & State == "CA", "So Cal",
ifelse(County == "Imperial" & State == "CA", "So Cal",
ifelse(County == "King" & State == "WA", "Seattle",
ifelse(County == "Snohomish" & State == "WA", "Seattle",
ifelse(County == "Pierce" & State == "WA", "Seattle",
ifelse(County == "Clackamas" & State == "OR", "Portland",
ifelse(County == "Columbia" & State == "OR", "Portland",
ifelse(County == "Multnomah" & State == "OR", "Portland",
ifelse(County == "Washington" & State == "OR", "Portland",
ifelse(County == "Yamhill" & State == "OR", "Portland",
ifelse(County == "Clark" & State == "WA", "Portland",
ifelse(County == "Skamania" & State == "WA", "Portland",
ifelse(County == "Denver" & State == "CO", "Denver",
ifelse(County == "Arapahoe" & State == "CO", "Denver",
ifelse(County == "Jefferson" & State == "CO", "Denver",
ifelse(County == "Adams" & State == "CO", "Denver",
ifelse(County == "Douglas" & State == "CO", "Denver",
ifelse(County == "Broomfield" & State == "CO", "Denver",
ifelse(County == "Elbert" & State == "CO", "Denver",
ifelse(County == "Park" & State == "CO", "Denver",
ifelse(County == "Clear Creek" & State == "CO", "Denver",
ifelse(County == "Alameda" & State == "CA", "Bay Area",
ifelse(County == "Contra Costa" & State == "CA", "Bay Area",
ifelse(County == "Marin" & State == "CA", "Bay Area",
ifelse(County == "Monterey" & State == "CA", "Bay Area",
ifelse(County == "Napa" & State == "CA", "Bay Area",
ifelse(County == "San Benito" & State == "CA", "Bay Area",
ifelse(County == "San Francisco" & State == "CA", "Bay Area",
ifelse(County == "San Mateo" & State == "CA", "Bay Area",
ifelse(County == "Santa Clara" & State == "CA", "Bay Area",
ifelse(County == "Santa Cruz" & State == "CA", "Bay Area",
ifelse(County == "Solano" & State == "CA", "Bay Area",
ifelse(County == "Sonoma" & State == "CA", "Bay Area",
NA))))))))))))))))))))))))))))))))))))))))))
dataclean <- dataclean %>%
mutate(region =
ifelse(County == "Kings" & State == "NY", "New York",
ifelse(County == "Queens" & State == "NY", "New York",
ifelse(County == "New York" & State == "NY", "New York",
ifelse(County == "Bronx" & State == "NY", "New York",
ifelse(County == "Richmond" & State == "NY", "New York",
ifelse(County == "Westchester" & State == "NY", "New York",
ifelse(County == "Bergen" & State == "NY", "New York",
ifelse(County == "Hudson" & State == "NY", "New York",
ifelse(County == "Passaic" & State == "NY", "New York",
ifelse(County == "Putnam" & State == "NY", "New York",
ifelse(County == "Rockland" & State == "NY", "New York",
ifelse(County == "Suffolk" & State == "NY", "New York",
ifelse(County == "Nassau" & State == "NY", "New York",
ifelse(County == "Middlesex" & State == "NJ", "New York",
ifelse(County == "Monmouth" & State == "NJ", "New York",
ifelse(County == "Ocean" & State == "NJ", "New York",
ifelse(County == "Somerset" & State == "NJ", "New York",
ifelse(County == "Essex" & State == "NJ", "New York",
ifelse(County == "Union" & State == "NJ", "New York",
ifelse(County == "Morris" & State == "NJ", "New York",
ifelse(County == "Sussex" & State == "NJ", "New York",
ifelse(County == "Hunterdon" & State == "NJ", "New York",
ifelse(County == "Pike" & State == "NJ", "New York",
region))))))))))))))))))))))))
# code nor cal region as all others in CA not already defined
dataclean <- dataclean %>%
mutate(region =
ifelse(State == "CA" & is.na(region) == TRUE, "Nor Cal", region))
#Removing Columns that provide no benefit
dataclean <- subset(dataclean,select = -c(Assignment.Number
,Assignment.has.Historical.Mngr
,Suffix
,Assignment.Date
,Assignment.Manager
,Assignment.Role
,Assignment.Title
,Assignment.Status
,Strategy
,Progress.Level
,Assignment.Group
,Assignment.Category
,Funding.Method
,Expected.Book.Date
,Qualification.Amount
,Expected.Book.Amount
,Expected.Book.Date
,Hard.Gift.Total
,Soft.Credit.Total
,Total.Assignment.Gifts
,No.of.Pledges
,Proposal..
,Proposal.Notes
,HH.Life.Spouse.Credit
,Last.Contact.By.Manager
,X..of.Contacts.By.Manager
,DonorSearch.Range
,iWave.Range
,WealthEngine.Range
,Philanthropic.Commitments
))
#cleaning up zip codes removing -4 after
dataclean$Zip <- gsub(dataclean$Zip, pattern="-.*", replacement = "")
#adding zip code data and column
zip <- read.csv(here::here("final_project", "Salary_Zipcode.csv"),
stringsAsFactors = FALSE,
strip.white = TRUE,
na.strings = "")
#adding zip salary column
dataclean <-dataclean %>%
mutate(zipcode_slry = VLOOKUP(Zip, zip, NAME, S1902_C03_002E))
#slry range
dataclean <- dataclean %>%
mutate(zipslry_range =
ifelse(zipcode_slry %in% 10000:89999, "90K-99K",
ifelse(zipcode_slry %in% 90000:99999, "90K-99K",
ifelse(zipcode_slry %in% 100000:149999, "100K-149K",
ifelse(zipcode_slry %in% 150000:199999, "150K-199K",
ifelse(zipcode_slry %in% 200000:249999, "200K-249K",
ifelse(zipcode_slry %in% 250000:299999, "250K-299K",
ifelse(zipcode_slry %in% 300000:349999, "300K-349K",
ifelse(zipcode_slry %in% 350000:399999, "350K-399K",
ifelse(zipcode_slry %in% 400000:499999, "400K-499K",
ifelse(zipcode_slry %in% 500000:999999, "500K-999K",
NA)))))))))))
sum(is.na(dataclean$zipcode_slry))
[1] 62347
#adding scholarship data (y/n)
schlr <- read.csv(here::here("final_project", "scholarship.csv"),
stringsAsFactors = FALSE,
strip.white = TRUE,
na.strings = "")
#adding scholarship column
dataclean <-dataclean %>%
mutate(scholarship = VLOOKUP(ID, schlr, ID, SCHOLARSHIP))
#replacing NA with 0
dataclean$scholarship <- replace_na(dataclean$scholarship,'0')
#replacing Y with 1
dataclean$scholarship<-ifelse(dataclean$scholarship=="Y",1,0)
#checking how many are N
table(dataclean$scholarship)
0 1
295264 27962
#checking and deleting scholarship column
class(dataclean$schlr_fct)
[1] "NULL"
dataclean = subset(dataclean, select = -c(scholarship))
#checking for duplicates N >1 indicates a records values are in the file twice
dataclean %>% group_by(ID) %>% count() %>% arrange(desc(n))
<<<<<<< HEAD
=======
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
#removing duplicated records
dataclean <- unique(dataclean)
#n = 1 no ID with multiple records cleaned of dupes
dataclean %>% group_by(ID) %>% count() %>% arrange(desc(n))
<<<<<<< HEAD
=======
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
NA
1d Creating many many factor variables
dataclean <-
dataclean %>%
#SEX
mutate(sex_fct =
fct_explicit_na(Sex),
sex_simple =
fct_lump_n(Sex, n = 4),
#MARRIED
married_fct =
fct_explicit_na(Married),
#DONOR SEGMENT
donorseg_fct =
fct_explicit_na(Donor.Segment),
donorseg_simple =
fct_lump_n(Donor.Segment, n = 4),
#CONTACT RULE
contact_fct =
fct_explicit_na(Contact.Rules),
contact_simple =
fct_lump_n(Contact.Rules, n = 4),
#SPOUSE MAIL
spomail_fct =
fct_explicit_na(Spouse.Mail.Rules),
spomail_simple =
fct_lump_n(Spouse.Mail.Rules, n = 4),
#JOB TITLE
jobtitle_fct =
fct_explicit_na(Job.Title),
jobtitle_simple =
fct_lump_n(Job.Title, n = 5),
#DEGREE TYPE 1
deg1_fct =
fct_explicit_na(Degree.Type.1),
deg1_simple =
fct_lump_n(Degree.Type.1, n = 5),
#DEGREE TYPE 2
deg2_fct =
fct_explicit_na(Degree.Type.2),
deg2_simple =
fct_lump_n(Degree.Type.2, n = 5),
#MAJOR 1
maj1_fct =
fct_explicit_na(Major.1),
maj1_simple =
fct_lump_n(Major.1, n = 5),
#MAJOR 2
maj2_fct =
fct_explicit_na(Major.2),
maj2_simple =
fct_lump_n(Major.2, n = 5),
#MINOR 1
min1_fct =
fct_explicit_na(Minor.1),
min1_simple =
fct_lump_n(Minor.1, n = 5),
#MINOR 2
min2_fct =
fct_explicit_na(Minor.2),
min2_simple =
fct_lump_n(Minor.2, n = 5),
#SCHOOL 1
school1_fct =
fct_explicit_na(School.1),
school1_simple =
fct_lump_n(School.1, n = 5),
#SCHOOL 2
school2_fct =
fct_explicit_na(School.2),
school2_simple =
fct_lump_n(School.2, n = 5),
#INSTITUTION TYPE
insttype_fct =
fct_explicit_na(Institution.Type),
insttype_simple =
fct_lump_n(Institution.Type, n = 5),
#EXTRACURRICULAR
extra_fct =
fct_explicit_na(Extracurricular),
extra_simple =
fct_lump_n(Extracurricular, n = 5),
#HH FIRST GIFT FUND
hhfirstgift_fct =
fct_explicit_na(HH.First.Gift.Fund),
hhfirstgift_simple =
fct_lump_n(HH.First.Gift.Fund, n = 5),
#CHILD 1 ENROLL STATUS
ch1_enroll_fct =
fct_explicit_na(Child.1.Enroll.Status),
ch1_enroll_simple =
fct_lump_n(Child.1.Enroll.Status, n = 4),
#CHILD 1 MAJOR
ch1_maj_fct =
fct_explicit_na(Child.1.Major),
ch1_maj_simple =
fct_lump_n(Child.1.Major, n = 4),
#CHILD 1 MINOR
ch1_min_fct =
fct_explicit_na(Child.1.Minor),
ch1_min_simple =
fct_lump_n(Child.1.Minor, n = 4),
#CHILD 1 SCHOOL
ch1_school_fct =
fct_explicit_na(Child.1.School),
ch1_school_simple =
fct_lump_n(Child.1.School, n = 4),
#CHILD 1 FEEDER
ch1_feeder_fct =
fct_explicit_na(Child.1.Feeder.School),
ch1_feeder_simple =
fct_lump_n(Child.1.Feeder.School, n = 4),
#CHILD 2 ENROLL STATUS
ch1_enroll_fct =
fct_explicit_na(Child.2.Enroll.Status),
ch2_enroll_simple =
fct_lump_n(Child.2.Enroll.Status, n = 4),
#CHILD 2 MAJOR
ch2_maj_fct =
fct_explicit_na(Child.2.Major),
ch2_maj_simple =
fct_lump_n(Child.2.Major, n = 4),
#CHILD 2 MINOR
ch2_min_fct =
fct_explicit_na(Child.2.Minor),
ch2_min_simple =
fct_lump_n(Child.2.Minor, n = 4),
#CHILD 2 SCHOOL
ch2_school_fct =
fct_explicit_na(Child.2.School),
ch2_school_simple =
fct_lump_n(Child.2.School, n = 4),
#CHILD 2 FEEDER
ch2_feeder_fct =
fct_explicit_na(Child.2.Feeder.School),
ch2_feeder_simple =
fct_lump_n(Child.2.Feeder.School, n = 4),
)
#checking to see if its a factor
#class(dataclean$sex_fct)
#class(dataclean$donorseg_fct)
#class(dataclean$contact_fct)
#class(dataclean$spomail_fct)
#checking levels
#levels(dataclean$sex_simple)
#levels(dataclean$donorseg_simple)
#levels(dataclean$contact_simple)
#levels(dataclean$spomail_simple)
#levels(dataclean$hhfirstgift_simple)
#creating a table against Sex column
#table(dataclean$sex_fct, dataclean$sex_simple)
DonorSegment Analysis
#grouping by donorsegment and analyzing
dataclean %>%
group_by(Donor.Segment) %>%
summarise(Count = length(Donor.Segment),
mean_total_giv = mean(HH.Lifetime.Giving)) %>%
arrange(-Count) %>%
filter(Count >= 100) %>%
#added scales package to have the values show in dollar
mutate(mean_total_giv = dollar(mean_total_giv)) %>%
kable(col.names = c("Donor Segment", "Count", "Mean HH Lifetime Giving"), align=rep('c', 3)) %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = F)
<<<<<<< HEAD
=======
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Donor Segment
Count
Mean HH Lifetime Giving
NA
231974
$0.00
Lost Donor
69718
$4,954.47
Lapsed Donor
11193
$10,069.79
Current Donor
5603
$90,638.32
Lapsing Donor
3862
$16,590.15
At-Risk Donor
650
$77,143.93
NA
NA
First gift size
aq <- quantile(dataclean$HH.First.Gift.Amount, probs = c(.25,.50,.75,.9,.99), na.rm = TRUE)
aq <- as.data.frame(aq)
aq$aq <- dollar(aq$aq)
aq %>%
kable(col.names = "Quantile") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = F)
<<<<<<< HEAD
=======
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Quantile
25%
$0.00
50%
$0.00
75%
$0.00
90%
$40.00
99%
$1,910.06
NA
NA
Consecutive giving
#consecutive years of giving
dataclean %>%
filter(Max.Consec.Fiscal.Years > 0) %>%
ggplot(aes(Max.Consec.Fiscal.Years)) + geom_histogram(fill = "#002845", bins = 20) +
theme_economist_white() +
ggtitle("Consecutive Years of Giving Distribution") +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(0,120,2)) +
scale_y_continuous(breaks = seq(0,10000000,5000))
<<<<<<< HEAD

=======

>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
NA
NA
NA
Lifetime giving based on number of children
dataclean %>%
filter(HH.Lifetime.Giving <= 10000) %>%
filter(HH.Lifetime.Giving > 0) %>%
mutate(`No_of_Children` = as.factor(`No_of_Children`)) %>%
ggplot(aes(HH.Lifetime.Giving, fill = `No_of_Children`)) + geom_histogram(bins = 30) + theme_economist_white() +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(0,100000,1000)) +
scale_y_continuous(breaks = seq(0,100000000,5000)) +
ggtitle("Giving distribution and number of children")+
scale_fill_manual(values=c("#002845", "#00cfcc", "#ff9973"))
<<<<<<< HEAD

=======

>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
NA
NA
NA
Mean, Median, and Count of Giving in Age Ranges
age_range_giving <- dataclean %>%
group_by(age_range) %>%
summarise(avg_giving = mean(HH.Lifetime.Giving, na.rm = TRUE),
med_giving = median(HH.Lifetime.Giving, na.rm = TRUE),
amount_of_people_in_age_range = n())
glimpse(age_range_giving)
<<<<<<< HEAD
Rows: 10
Columns: 4
$ age_range <chr> "10 < 20 years old", "20 < 30 years old", "30 < 40 years old", "40 < 50 years old", "50 < 60 years o~
$ avg_giving <dbl> 0.4455282, 28.2744487, 391.1692413, 804.5846468, 2779.1345908, 5401.7068276, 11571.3819147, 24366.90~
$ med_giving <dbl> 0, 0, 0, 0, 0, 0, 0, 10, 15, 0
$ amount_of_people_in_age_range <int> 3985, 24551, 21024, 16831, 20737, 18226, 12195, 5954, 6626, 192871
=======
Rows: 10
Columns: 4
$ age_range <chr> "10 < 20 years old", "20 < 30 …
$ avg_giving <dbl> 0.4449699, 28.2733731, 391.223…
$ med_giving <dbl> 0, 0, 0, 0, 0, 0, 0, 10, 15, 0
$ amount_of_people_in_age_range <int> 3990, 24553, 21021, 16837, 207…
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094
Part 2
2a) Plotting average giving by age range
age_range_giving <-
age_range_giving %>%
mutate(age_range = factor(age_range))
ggplot(age_range_giving, aes(age_range, avg_giving)) +
geom_bar(stat = "identity")+
theme(axis.text.x = element_text(angle=45,
hjust=1))

NA
NA
2b) Count of donors based on age range (another way to look at it)
ggplot(dataclean,
aes(age_range)) +
geom_bar() +
theme(axis.text.x = element_text(angle=45,
hjust=1)) +
labs(title = "Count of Age Ranges", x = "", y = "")

NA
NA
2c) Boxplot of the Age Ranges Against the Lifetime Giving Amounts with a log scale applied - the reason we applied log scale is to resolve issues with visualizations that skew towards large values in our dataset.
ggplot(dataclean, aes(age_range,HH.Lifetime.Giving,fill = age_range)) +
geom_boxplot(
outlier.colour = "red") +
scale_y_log10() +
theme(axis.text.x=element_text(angle=45,hjust=1))

NA
NA
2d) Splitting by age and gender
#creating boxplots
dataclean %>%
filter(Age < 100) %>% #removing the weird outliers that are over 100
filter(Sex %in% c("M", "F")) %>%
ggplot(aes(Sex, Age)) +
geom_boxplot() +
theme_economist() +
ggtitle("Ages of Donors Based on Gender") +
xlab(NULL) + ylab(NULL)

NA
NA
Giving by gender
#remove NAs U X
q <- ggplot(dataclean)
q + stat_summary_bin(
aes(y = HH.Lifetime.Giving, x = sex_simple),
fun.y = "mean", geom = "bar")

summary(dataclean$sex_simple)
F M U X NA's
120781 108190 3683 7 90339
Mean age by gender
#breakdown of sexs
tally(group_by(dataclean, Sex))
summarize(group_by(dataclean, Sex),
avg_giving = mean(HH.Lifetime.Giving, na.rm = TRUE),
avg_age = mean(Age, na.rm = TRUE),
med_age = median(Age, na.rm = TRUE))
#grouping by sex and age range for slides
tally(group_by(dataclean, Sex, age_range))
NA
NA
NA
2e) Distribution of people in the states that they live.
dataclean %>%
mutate(State = ifelse(State == " ", "NA", State)) %>%
filter(State != "NA") %>%
group_by(State) %>%
summarise(Count = length(State)) %>%
filter(Count > 800) %>%
arrange(-Count) %>%
kable(col.names = c("Donor's State", "Count")) %>%
kable_styling(bootstrap_options = c("condensed"),
full_width = F)
Donor's State
Count
CA
176487
WA
7957
TX
7266
NY
5659
CO
5073
AZ
4925
OR
4612
FL
4111
IL
3681
HI
3394
PA
2904
OH
2754
NV
2715
MI
2523
MA
2473
NJ
2311
VA
2158
NC
2085
GA
2044
MO
1889
MN
1732
MD
1488
TN
1443
IN
1417
CT
1380
WI
1330
UT
1173
OK
1151
AL
1120
LA
1110
ID
1096
SC
1076
KY
1032
KS
1027
NM
981
IA
880
NA
NA
NA
NA
NA
NA
2f) Looking at all donors first gift amount. 75% made a first gift of <100.
no_non_donors <- dataclean %>%
filter(Lifetime.Giving != 0)
nd <- quantile(no_non_donors$HH.First.Gift.Amount, probs = c(.25,.50,.75,.9,.99), na.rm = TRUE)
nd <- as.data.frame(nd)
nd %>%
kable(col.names = "Quantile") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = F)
Quantile
25%
3.8
50%
25.0
75%
100.0
90%
500.0
99%
15000.0
NA
NA
NA
NA
Modeling for you
Split data
#converting married Y and N to 1 and 0
dataclean <- dataclean %>%
mutate(Married_simple = ifelse(Married == "N",0,1))
dataclean <- dataclean %>%
mutate(hh.lifetime.giving_fct = as.factor(HH.Lifetime.Giving))
library("rsample")
data_split <- initial_split(dataclean, prop = 0.75)
data_train <- training(data_split)
data_test <- testing(data_split)
p <- dataclean %>%
ggplot(aes(Age)) + geom_histogram(bins=30, fill = "blue") + theme_economist_white() +
ggtitle("Overall Donor Age Distribution") +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(5,100,by = 20)) +
scale_y_continuous(breaks = seq(20,100,by = 20)) + xlim(c(20,100))
Scale for 'x' is already present. Adding another scale for 'x',
which will replace the existing scale.
ggplotly(p)
p

ggplot(data = dataclean, aes(x = Age)) + geom_histogram(fill ="blue")+ xlim(c(20,100))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

NA
NA
NA
Another Histogram
dataclean %>%
filter(Age >= 10) %>%
filter(Age <= 90) %>%
ggplot(aes(Age)) + geom_histogram(fill = "#002845", bins = 20) + theme_economist_white() +
ggtitle("Overall Donor Age Distribution") +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(0,120,5)) +
scale_y_continuous(breaks = seq(0,10000000,2000))

Age distribution by gender
#Age Gender filtered out below 15 and above 90 - also removed U X the weird values
dataclean %>%
filter(Age >= 15) %>%
filter(Age <= 90) %>%
mutate(Sex = as.factor(Sex)) %>%
filter(Sex != "U") %>%
filter(Sex != "X") %>%
ggplot(aes(Age, fill = Sex)) + geom_histogram(bins = 25) + theme_economist_white() +
ggtitle("Age Distribution by Gender") +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(0,120,10)) +
scale_y_continuous(breaks = seq(0,50000,2000)) + scale_fill_manual(values=c("#ff9973", "#00cfcc"))

Donor age distribution by marital status
#Age Marital Status
dataclean %>%
filter(Age >= 20) %>%
filter(Age <= 85) %>%
ggplot(aes(Age, fill = Married)) + geom_histogram(bins = 25) + theme_economist_white() +
ggtitle("Overall Donor Age Distribution by Marital Status") +
xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(0,120,5)) +
scale_y_continuous(breaks = seq(0,50000,2000)) + scale_fill_manual(values=c("#ff9973", "#00cfcc"))

Linear Model
ggplot(data = data_train, aes(x = Age, y = log(Lifetime.Giving))) + geom_point(alpha = 1/10) + geom_smooth(method = lm) + facet_wrap(~No_of_Children) + theme_clean(base_size = 8) + labs(x = "X", y = "Y") +
ggtitle("Title")
`geom_smooth()` using formula 'y ~ x'

MORE MODELS
Big logistic model
# Set family to binomial to set logistic function
# Run the model on the training set
donor_logit1 <-
glm(hh.lifetime.giving_fct ~ Married_simple,
family = "binomial",
data = data_train)
summary(donor_logit1)
Call:
glm(formula = hh.lifetime.giving_fct ~ Married_simple, family = "binomial",
data = data_train)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.1122 -0.6872 -0.6872 1.2440 1.7659
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -1.323203 0.005906 -224.1 <0.0000000000000002 ***
Married_simple 1.167887 0.009628 121.3 <0.0000000000000002 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 288365 on 242249 degrees of freedom
Residual deviance: 273662 on 242248 degrees of freedom
AIC: 273666
Number of Fisher Scoring iterations: 4
donor_logit2 <-
glm(hh.lifetime.giving_fct ~ No_of_Children,
family = "binomial",
data = data_train)
summary(donor_logit2)
Call:
glm(formula = hh.lifetime.giving_fct ~ No_of_Children, family = "binomial",
data = data_train)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.9083 -0.8000 -0.8000 1.5411 1.6094
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.975131 0.005212 -187.10 <0.0000000000000002 ***
No_of_Children 0.151469 0.009049 16.74 <0.0000000000000002 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 288365 on 242249 degrees of freedom
Residual deviance: 288089 on 242248 degrees of freedom
AIC: 288093
Number of Fisher Scoring iterations: 4
#summary(data_train$major_gifter)
donor_logit3 <-
glm(major_gifter ~ Married_simple + No_of_Children + donorseg_simple + Assignment_flag + Total.Giving.Years,
family = "binomial",
data = data_train)
summary(donor_logit3)
Call:
glm(formula = major_gifter ~ Married_simple + No_of_Children +
donorseg_simple + Assignment_flag + Total.Giving.Years, family = "binomial",
data = data_train)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.4932 -0.1410 -0.1220 -0.0873 3.5040
Coefficients:
Estimate Std. Error z value
(Intercept) -4.08066 0.24408 -16.718
Married_simple -1.23973 0.08749 -14.170
No_of_Children 0.71530 0.05765 12.407
donorseg_simpleCurrent Donor -0.04313 0.24679 -0.175
donorseg_simpleLapsed Donor -0.60244 0.25434 -2.369
donorseg_simpleLapsing Donor -0.40470 0.26802 -1.510
donorseg_simpleLost Donor -0.96219 0.24415 -3.941
Assignment_flag 1.19911 0.11744 10.210
Total.Giving.Years 0.14559 0.00441 33.013
Pr(>|z|)
(Intercept) < 0.0000000000000002 ***
Married_simple < 0.0000000000000002 ***
No_of_Children < 0.0000000000000002 ***
donorseg_simpleCurrent Donor 0.8613
donorseg_simpleLapsed Donor 0.0179 *
donorseg_simpleLapsing Donor 0.1311
donorseg_simpleLost Donor 0.0000811 ***
Assignment_flag < 0.0000000000000002 ***
Total.Giving.Years < 0.0000000000000002 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 9764.4 on 68404 degrees of freedom
Residual deviance: 7544.5 on 68396 degrees of freedom
(173845 observations deleted due to missingness)
AIC: 7562.5
Number of Fisher Scoring iterations: 8
exp(donor_logit3$coefficients)
(Intercept) Married_simple
0.01689628 0.28946282
No_of_Children donorseg_simpleCurrent Donor
2.04479757 0.95778285
donorseg_simpleLapsed Donor donorseg_simpleLapsing Donor
0.54747539 0.66717987
donorseg_simpleLost Donor Assignment_flag
0.38205405 3.31714962
Total.Giving.Years
1.15672540
#training predictions for in sample preds
preds_train <- predict(donor_logit3, newdata = data_train, type = "response")
#test predicts for OOS (out of sample)
preds_test <- predict(donor_logit3, newdata = data_test, type = "response")
head(preds_train)
196454 181024 64789 23864 86886
NA 0.003806297 NA NA NA
188620
NA
head(preds_test)
1 6 17 18 21
0.047220650 0.764137284 0.931364886 0.001865082 0.040099014
27
0.188797205
results_train <- data.frame(
`truth` = data_train %>% select(major_gifter) %>%
mutate(major_gifter = as.numeric(major_gifter)),
`Class1` = preds_train,
`type` = rep("train",length(preds_train))
)
results_test <- data.frame(
`truth` = data_test %>% select(major_gifter) %>%
mutate(major_gifter = as.numeric(major_gifter)),
`Class1` = preds_test,
`type` = rep("test",length(preds_test))
)
results <- bind_rows(results_train,results_test)
dim(results_train)
[1] 242250 3
dim(results_test)
[1] 80750 3
dim(results)
[1] 323000 3
library('plotROC')
p_plot <-
ggplot(results,
aes(m = Class1, d = major_gifter, color = type)) +
geom_roc(labelsize = 2.5,
#Took the labelsize down to avoid cutoff
cutoffs.at = c(0.7,0.5,0.3,0.1,0)) +
#We removed some of the cutoffs to avoid the mashup near the origin.
#Changed the theme to avoid cutoff plot values.
theme_classic(base_size = 14) +
labs(x = "False Positive Rate",
y = "True Positive Rate") +
ggtitle("ROC Plot: Training and Test")
print(p_plot)

p_train <-
ggplot(results_train,
aes(m = Class1, d = major_gifter, color = type)) +
geom_roc(labelsize = 3.5,
cutoffs.at = c(0.7,0.5,0.3,0.1,0)) +
theme_minimal(base_size = 16) +
labs(x = "False Positive Rate",
y = "True Positive Rate") +
ggtitle("ROC Plot: Training and Test")
p_test <-
ggplot(results_test,
aes(m = Class1, d = major_gifter, color = type)) +
geom_roc(labelsize = 3.5,
cutoffs.at = c(0.7,0.5,0.3,0.1,0)) +
theme_minimal(base_size = 16) +
labs(x = "False Positive Rate",
y = "True Positive Rate") +
ggtitle("ROC Plot: Training and Test")
#Calculating AUC of both
print(calc_auc(p_train)$AUC)
[1] 0.8823867
print(calc_auc(p_test)$AUC)
[1] 0.8713205
RIDGE
library('glmnet')
library('glmnetUtils')
ridge_fit1 <- cv.glmnet(HH.Lifetime.Giving ~ sex_fct + donorseg_fct + No_of_Children,
data = data_train,
alpha = 0)
#Alpha 0 sets the Ridge
print(ridge_fit1)
print(ridge_fit1$lambda.min)
print(ridge_fit1$lambda.1se)
LASSO

coef(lasso_fit)
36 x 1 sparse Matrix of class "dgCMatrix"
s1
(Intercept) 5406.897
jobtitle_simpleAttorney .
jobtitle_simpleOwner .
jobtitle_simplePresident .
jobtitle_simpleTeacher .
jobtitle_simpleUnknown Position .
jobtitle_simpleOther .
deg1_simpleBachelor of Arts .
deg1_simpleBachelor of Fine Arts .
deg1_simpleBachelor of Science .
deg1_simpleMaster of Arts .
deg1_simpleNon Degree - Undergraduate .
deg1_simpleOther .
school1_simpleCollege of Health and Behavioral Sciences .
school1_simpleDonna Ford Attallah College of Educational Studies .
school1_simpleGeorge L. Argyros School of Business and Economics .
school1_simpleLawrence and Kristina Dodge Coll of Film & Media .
school1_simpleWilkinson Coll of Arts Humanities & Soc Sciences .
school1_simpleOther .
hhfirstgift_simpleChapman Annual Scholarship Fund .
hhfirstgift_simpleChapman Fund .
hhfirstgift_simpleJog-A-Thon .
hhfirstgift_simplePhonathon .
hhfirstgift_simplePre-SRN Conversion Gift History .
hhfirstgift_simpleOther .
maj1_simpleBusiness Administration BS .
maj1_simpleEducation .
maj1_simpleLaw (Full-Time) .
maj1_simpleUndecided - UG .
maj1_simpleUnknown Major .
maj1_simpleOther .
donorseg_simpleAt-Risk Donor .
donorseg_simpleCurrent Donor .
donorseg_simpleLapsed Donor .
donorseg_simpleLapsing Donor .
donorseg_simpleLost Donor .
#enet_mod <- cva.glmnet(dependent ~ indy1 + indy2,
# data = data,
# alpha = seq(0,1, by = 0.1))
#print(enet_mod)
#plot(enet_mod)
ELASTICNET
minlossplot(enet_mod,
cv.type = "min")
get_alpha <- function(fit) {
alpha <- fit$alpha
error <- sapply(fit$modlist,
function(mod) {min(mod$cvm)})
alpha[which.min(error)]
}
get_model_params <- function(fit) {
alpha <- fit$alpha
lambdaMin <- sapply(fit$modlist, `[[`, "lambda.min")
lambdaSE <- sapply(fit$modlist, `[[`, "lambda.1se")
error <- sapply(fit$modlist, function(mod) {min(mod$cvm)})
best <- which.min(error)
data.frame(alpha = alpha[best], lambdaMin = lambdaMin[best],
lambdaSE = lambdaSE[best], eror = error[best])
}
best_alpha <- get_alpha(enet_mod)
print(best_alpha)
get_model_params(enet_mod)
best_mod <- enet_mod$modlist[[which(enet_mod$alpha == best_alpha)]]
print(best_mod)
Ridges plot - could be useful for plotting donations vs donor segment
library('ggridges')
summary(data_train$variable)
ggplot(data_train, aes(x = HH.Lifetime.Giving, y = donorseg_fct)) + geom_density_ridges(rel_min_height = 0.005) + xlim(c(0, 400)) +
ggtitle("HH Lifetime Giving by Donor Segment")
library('corrplot')
#removing ID zip and nonnumeric
corrplot_data <- dataclean[-c(1:47,55:56,58:130)]
#Convert from character to numeric data type
convert_fac2num <- function(x){
as.numeric(as.factor(x))
}
corrplot_data <- mutate_at(corrplot_data,
.vars = c(1:8),
.funs = convert_fac2num)
#making a matrix
cd_cor <- cor(corrplot_data)
#creating correlation
col <- colorRampPalette(c("#BB4400", "#EE9990",
"#FFFFFF", "#77AAEE", "#4477BB"))
corrplot(cd_cor, method="color", col=col(100),
type="lower", addCoef.col = "black",
tl.pos="lt", tl.col="black",
tl.cex=0.7, tl.srt=45,
number.cex=0.7,
diag=FALSE)
Random Forest
library('randomForest')
rf_fit_donor <- randomForest(dependent ~ .,
data = data_train,
type = classification,
mtry = 7,
na.action = na.roughfix,
ntree = 200,
importance=TRUE
)
print(rf_fit_donor)
varImpPlot(rf_fit_donor, sort = TRUE,
n.var = 5,
type = 2, class = NULL, scale = TRUE,
main = deparse(substitute(rf_fit_donor)))
library('randomForestExplainer')
plot_min_depth_distribution(
rf_fit_donor,
k = 10,
min_no_of_trees = 0,
mean_sample = "top_trees",
mean_scale = FALSE,
mean_round = 2,
main = "Distribution of minimal depth and its mean"
)
#Splitting Category out to check if the category is useful for analysis
data_category_split_out <- dataclean %>%
mutate(Category.Codes = trim(strsplit(as.character(Category.Codes), "|", fixed = TRUE))) %>%
unnest(Category.Codes) %>% pivot_wider(names_from = Category.Codes,values_from =Category.Codes, values_fn = length)
<<<<<<< HEAD
LS0tDQp0aXRsZTogIkJST0NPREUgU3VtbWFyeSBTdGF0aXN0aWNzIg0KYXV0aG9yOiAiQWFyb24gV2lsbGlzLCBDYW5ub24gQnJvb2tlLCBKb3NodWEgSGVuZGVyc29uLCBSeWFuIFJhZGNsaWZmIg0Kc3VidGl0bGU6IEJVUzY5NiBGaW5hbCBQcm9qZWN0IHYxMg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQoNCiMgUGxlYXNlIGxlYXZlIHRoaXMgY29kZSBjaHVuayBhcyBpcy4gSXQgbWFrZXMgc29tZSBzbGlnaHQgZm9ybWF0dGluZyBjaGFuZ2VzIHRvIGFsdGVyIHRoZSBvdXRwdXQgdG8gYmUgbW9yZSBhZXN0aGV0aWNhbGx5IHBsZWFzaW5nLiANCg0KbGlicmFyeSgna25pdHInKQ0KDQoNCiMgQ2hhbmdlIHRoZSBudW1iZXIgaW4gc2V0IHNlZWQgdG8geW91ciBvd24gZmF2b3JpdGUgbnVtYmVyDQpzZXQuc2VlZCgxODE4KQ0Kb3B0aW9ucyh3aWR0aD03MCkNCm9wdGlvbnMoc2NpcGVuPTk5KQ0KDQoNCiMgdGhpcyBzZXRzIHRleHQgb3V0cHV0dGVkIGluIGNvZGUgY2h1bmtzIHRvIHNtYWxsDQpvcHRzX2NodW5rJHNldCh0aWR5Lm9wdHM9bGlzdCh3aWR0aC53cmFwPTUwKSx0aWR5PVRSVUUsIHNpemUgPSAidnNtYWxsIikgIA0Kb3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIyAiY2FjaGluZyIgc3RvcmVzIG9iamVjdHMgaW4gY29kZSBjaHVua3MgYW5kIG9ubHkgcmV3cml0ZXMgaWYgeW91IGNoYW5nZSB0aGluZ3MNCiAgICAgICAgICAgICAgIGNhY2hlID0gVFJVRSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAjIGF1dG9tYXRpY2FsbHkgZG93bmxvYWRzIGRlcGVuZGVuY3kgZmlsZXMNCiAgICAgICAgICAgICAgIGF1dG9kZXAgPSBUUlVFLA0KICAgICAgICAgICAgICAgIyANCiAgICAgICAgICAgICAgIGNhY2hlLmNvbW1lbnRzID0gRkFMU0UsDQogICAgICAgICAgICAgICAjIA0KICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLA0KICAgICAgICAgICAgICAgIyBjaGFuZ2UgZmlnLndpZHRoIGFuZCBmaWcuaGVpZ2h0IHRvIGNoYW5nZSB0aGUgY29kZSBoZWlnaHQgYW5kIHdpZHRoIGJ5IGRlZmF1bHQNCiAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDUuNSwgIA0KICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDQuNSwNCiAgICAgICAgICAgICAgIGZpZy5hbGlnbj0nY2VudGVyJykNCg0KDQpgYGANCg0KYGBge3Igc2V0dXAtMn0NCg0KIyBBbHdheXMgcHJpbnQgdGhpcyBvdXQgYmVmb3JlIHlvdXIgYXNzaWdubWVudA0Kc2Vzc2lvbkluZm8oKQ0KZ2V0d2QoKQ0KDQpgYGANCg0KDQo8IS0tICMjIyBzdGFydCBhbnN3ZXJpbmcgeW91ciBwcm9ibGVtIHNldCBoZXJlIC0tPg0KPCEtLSBZb3UgbWF5IGV4cG9ydCB5b3VyIGhvbWV3b3JrIGluIGVpdGhlciBodG1sIG9yIHBkZiwgd2l0aCB0aGUgZm9ybWVyIHVzdWFsbHkgYmVpbmcgZWFzaWVyLiANCiAgICAgVG8gZXhwb3J0IG9yIGNvbXBpbGUgeW91ciBSbWQgZmlsZTogY2xpY2sgYWJvdmUgb24gJ0tuaXQnIHRoZW4gJ0tuaXQgdG8gSFRNTCcgLS0+DQo8IS0tIEJlIHN1cmUgdG8gc3VibWl0IGJvdGggeW91ciAuUm1kIGZpbGUgYW5kIHRoZSBjb21waWxlZCAuaHRtbCBvciAucGRmIGZpbGUgZm9yIGZ1bGwgY3JlZGl0IC0tPg0KDQoNCmBgYHtyIHNldHVwLTN9DQoNCiMgbG9hZCBhbGwgeW91ciBsaWJyYXJpZXMgaW4gdGhpcyBjaHVuayANCmxpYnJhcnkoJ3RpZHl2ZXJzZScpDQpsaWJyYXJ5KCJmcyIpDQpsaWJyYXJ5KCdoZXJlJykNCmxpYnJhcnkoJ2RwbHlyJykNCmxpYnJhcnkoJ3RpZHl2ZXJzZScpDQpsaWJyYXJ5KCdnZ3Bsb3QyJykNCmxpYnJhcnkoJ2dncmVwZWwnKQ0KbGlicmFyeSgnZ2d0aGVtZXMnKQ0KbGlicmFyeSgnZm9yY2F0cycpDQpsaWJyYXJ5KCdyc2FtcGxlJykNCmxpYnJhcnkoJ2x1YnJpZGF0ZScpDQpsaWJyYXJ5KCdnZ3RoZW1lcycpDQpsaWJyYXJ5KCdrYWJsZUV4dHJhJykNCmxpYnJhcnkoJ3Bhc3RlY3MnKQ0KbGlicmFyeSgndmlyaWRpcycpDQpsaWJyYXJ5KCdwbG90bHknKQ0KbGlicmFyeSgndGlkeXF1YW50JykNCmxpYnJhcnkoJ3NjYWxlcycpDQpsaWJyYXJ5KCJnZGF0YSIpDQoNCiMgbm90ZSwgZG8gbm90IHJ1biBpbnN0YWxsLnBhY2thZ2VzKCkgaW5zaWRlIGEgY29kZSBjaHVuay4gaW5zdGFsbCB0aGVtIGluIHRoZSBjb25zb2xlIG91dHNpZGUgb2YgYSBjb2RlIGNodW5rLiANCg0KYGBgDQoNCg0KDQojIyBQYXJ0IDEgLSBGaW5hbCBQcm9qZWN0IENsZWFuaW5nIGFuZCBTdW1tYXJ5IFN0YXRpc3RpY3MgDQoNCjFhKSBMb2FkaW5nIGRhdGENCg0KYGBge3J9DQoNCiNSZWFkaW5nIHRoZSBkYXRhIGluIGFuZCBkb2luZyBtaW5vciBpbml0aWFsIGNsZWFuaW5nIGluIHRoZSBmdW5jdGlvbiBjYWxsDQojUmVwcm9kdWNpYmxlIGRhdGEgYW5hbHlzaXMgc2hvdWxkIGF2b2lkIGFsbCBhdXRvbWF0aWMgc3RyaW5nIHRvIGZhY3RvciBjb252ZXJzaW9ucy4NCiNzdHJpcC53aGl0ZSByZW1vdmVzIHdoaXRlIHNwYWNlIA0KI25hLnN0cmluZ3MgaXMgYSBzdWJzdGl0dXRpb24gc28gYWxsIHRoYXQgaGF2ZSAiIiB3aWxsID0gbmENCmRhdGEgPC0gcmVhZC5jc3YoaGVyZTo6aGVyZSgiZmluYWxfcHJvamVjdCIsICJkb25vcl9kYXRhLmNzdiIpLA0KICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsDQogICAgICAgICAgICAgICAgIHN0cmlwLndoaXRlID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncyA9ICIiKQ0KDQoNCg0KYGBgDQoNCg0KMWIpIEZpeGluZyB0aGUgd29ua3kgRE9CICYgRGF0YSBjbGVhbnVwDQoNCmBgYHtyfQ0KDQojKEJpcnRoZGF0ZSBhbmQgQWdlLCBJRCBhcyBhIG51bWJlcilhZGRpbmcgRE9CIChBZ2UvU3BvdXNlIEFnZSkgaW4geWVhcnMgY29sdW1ucyBhbmQgYWRkaW5nIHR3byBmaWVsZHMgZm9yIGFzc2lnbm1lbnQgYW5kIG51bWJlciBvZiBjaGlsZHJlbg0KZGF0YWNsZWFuIDwtIGRhdGEgJT4lDQogIG11dGF0ZShCaXJ0aGRhdGUgPSBpZmVsc2UoQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIEJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoQmlydGhkYXRlID0gbWR5KEJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhmbG9vcihpbnRlcnZhbChzdGFydD0gQmlydGhkYXRlLCBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpICU+JQ0KICBtdXRhdGUoU3BvdXNlLkJpcnRoZGF0ZSA9IGlmZWxzZShTcG91c2UuQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIFNwb3VzZS5CaXJ0aGRhdGUpKSAlPiUNCiAgbXV0YXRlKFNwb3VzZS5CaXJ0aGRhdGUgPSBtZHkoU3BvdXNlLkJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoU3BvdXNlLkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IFNwb3VzZS5CaXJ0aGRhdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpICU+JQ0KICBtdXRhdGUoSUQgPSBhcy5udW1lcmljKElEKSkgJT4lIA0KICBtdXRhdGUoQXNzaWdubWVudF9mbGFnID0gaWZlbHNlKGlzLm5hKEFzc2lnbm1lbnQuTnVtYmVyKSwgMCwxKSkgJT4lIA0KICBtdXRhdGUoIE5vX29mX0NoaWxkcmVuID0gaWZlbHNlKGlzLm5hKENoaWxkLjEuSUQpLDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKENoaWxkLjIuSUQpLDEsMikpKQ0KDQojY29uZmVycmFsIGRhdGVzDQpkYXRhY2xlYW4gPC0gZGF0YWNsZWFuICU+JQ0KICANCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjEgPSBpZmVsc2UoQ29uZmVycmFsLkRhdGUuMSA9PSAiMDAwMS0wMS0wMSIsIE5BLCBDb25mZXJyYWwuRGF0ZS4xKSkgJT4lDQogIG11dGF0ZShDb25mZXJyYWwuRGF0ZS4xID0gbWR5KENvbmZlcnJhbC5EYXRlLjEpKSAlPiUNCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjEuQWdlID0gYXMubnVtZXJpYyhmbG9vcihpbnRlcnZhbChzdGFydD0gQ29uZmVycmFsLkRhdGUuMSwgZW5kPVN5cy5EYXRlKCkpL2R1cmF0aW9uKG49MSwgdW5pdD0ieWVhcnMiKSkpKSAlPiUNCiAgDQogIG11dGF0ZShDb25mZXJyYWwuRGF0ZS4yID0gaWZlbHNlKENvbmZlcnJhbC5EYXRlLjIgPT0gIjAwMDEtMDEtMDEiLCBOQSwgQ29uZmVycmFsLkRhdGUuMikpICU+JQ0KICBtdXRhdGUoQ29uZmVycmFsLkRhdGUuMiA9IG1keShDb25mZXJyYWwuRGF0ZS4yKSkgJT4lDQogIG11dGF0ZShDb25mZXJyYWwuRGF0ZS4yLkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IENvbmZlcnJhbC5EYXRlLjIsIGVuZD1TeXMuRGF0ZSgpKS9kdXJhdGlvbihuPTEsIHVuaXQ9InllYXJzIikpKSkgJT4lDQogIA0KICBtdXRhdGUoTGFzdC5Db250YWN0LkJ5LkFueW9uZSA9IGlmZWxzZShMYXN0LkNvbnRhY3QuQnkuQW55b25lID09ICIwMDAxLTAxLTAxIiwgTkEsIExhc3QuQ29udGFjdC5CeS5BbnlvbmUpKSAlPiUNCiAgbXV0YXRlKExhc3QuQ29udGFjdC5CeS5BbnlvbmUgPSBtZHkoTGFzdC5Db250YWN0LkJ5LkFueW9uZSkpICU+JQ0KICBtdXRhdGUoTGFzdC5Db250YWN0LkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IExhc3QuQ29udGFjdC5CeS5BbnlvbmUsIGVuZD1TeXMuRGF0ZSgpKS9kdXJhdGlvbihuPTEsIHVuaXQ9InllYXJzIikpKSkgJT4lDQogIA0KIG11dGF0ZShISC5GaXJzdC5HaWZ0LkRhdGUgPSBpZmVsc2UoSEguRmlyc3QuR2lmdC5EYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIEhILkZpcnN0LkdpZnQuRGF0ZSkpICU+JQ0KICBtdXRhdGUoSEguRmlyc3QuR2lmdC5EYXRlID0gbWR5KEhILkZpcnN0LkdpZnQuRGF0ZSkpICU+JQ0KbXV0YXRlKEhILkZpcnN0LkdpZnQuQWdlID0gYXMubnVtZXJpYyhmbG9vcihpbnRlcnZhbChzdGFydD0gSEguRmlyc3QuR2lmdC5EYXRlLCBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpDQoNCiNtYWpvciBnaWZ0IA0KZGF0YWNsZWFuIDwtIA0KICBkYXRhY2xlYW4gJT4lIA0KICBtdXRhdGUobWFqb3JfZ2lmdGVyID0gaWZlbHNlKExpZmV0aW1lLkdpdmluZyA+IDUwMDAwLCAxLDApICU+JSBmYWN0b3IoLiwgbGV2ZWxzID0gYygiMCIsIjEiKSkpDQoNCg0KI3NwbGl0dGluZyB1cCB0aGUgYWdlIGludG8gcmFuZ2VzIGFuZCBjcmVhdGluZyBjYXRlZ29yeSBmb3IgZWFzeSB2aXN1YWxpemF0aW9uIA0KZGF0YWNsZWFuIDwtIGRhdGFjbGVhbiAlPiUNCiAgbXV0YXRlKGFnZV9yYW5nZSA9IA0KICAgIGlmZWxzZShBZ2UgJWluJSAxMDoxOSwgIjEwIDwgMjAgeWVhcnMgb2xkIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgMjA6MjksICIyMCA8IDMwIHllYXJzIG9sZCIsIA0KICAgIGlmZWxzZShBZ2UgJWluJSAzMDozOSwgIjMwIDwgNDAgeWVhcnMgb2xkIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgNDA6NDksICI0MCA8IDUwIHllYXJzIG9sZCIsDQogICAgaWZlbHNlKEFnZSAlaW4lIDUwOjU5LCAiNTAgPCA2MCB5ZWFycyBvbGQiLA0KICAgIGlmZWxzZShBZ2UgJWluJSA2MDo2OSwgIjYwIDwgNzAgeWVhcnMgb2xkIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgNzA6NzksICI3MCA8IDgwIHllYXJzIG9sZCIsDQogICAgaWZlbHNlKEFnZSAlaW4lIDgwOjg5LCAiODAgPCA5MCB5ZWFycyBvbGQiLA0KICAgIGlmZWxzZShBZ2UgJWluJSA5MDoxMjAsICI5MCsgeWVhcnMgb2xkIiwNCiAgICBOQSkpKSkpKSkpKSkNCg0KDQojc2VlaW5nIHdoYXQgd2UgaGF2ZQ0KdGFibGUoZGF0YWNsZWFuJGFnZV9yYW5nZSkNCiM1MC02MCBpcyB0aGUgbW9zdCBjb21tb24gYWdlIHJhbmdlIA0KDQojY3JlYXRpbmcgYSByZWdpb24gY29sdW1uIHVzaW5nIHRoZSBjb3VudHkgZGF0YSBhbmQgdGhlIE9NQiBNU0EgKE1ldHJvcG9saXRhbiBTdGF0aXN0aWNhbCBBcmVhKSBkZWZpbml0aW9ucw0KDQpkYXRhY2xlYW4gPC0gZGF0YWNsZWFuICU+JQ0KICBtdXRhdGUocmVnaW9uID0gDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FuIEx1aXMgT2Jpc3BvIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIktlcm4iICYgU3RhdGUgPT0gIkNBIiwgIlNvIENhbCIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FuIEJlcm5hcmRpbm8iICYgU3RhdGUgPT0gIkNBIiwgIlNvIENhbCIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FudGEgQmFyYmFyYSIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJWZW50dXJhIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkxvcyBBbmdlbGVzIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIk9yYW5nZSIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJSaXZlcnNpZGUiICYgU3RhdGUgPT0gIkNBIiwgIlNvIENhbCIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FuIERpZWdvIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkltcGVyaWFsIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIktpbmciICYgU3RhdGUgPT0gIldBIiwgIlNlYXR0bGUiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlNub2hvbWlzaCIgJiBTdGF0ZSA9PSAiV0EiLCAiU2VhdHRsZSIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiUGllcmNlIiAmIFN0YXRlID09ICJXQSIsICJTZWF0dGxlIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJDbGFja2FtYXMiICYgU3RhdGUgPT0gIk9SIiwgIlBvcnRsYW5kIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJDb2x1bWJpYSIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIk11bHRub21haCIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIldhc2hpbmd0b24iICYgU3RhdGUgPT0gIk9SIiwgIlBvcnRsYW5kIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJZYW1oaWxsIiAmIFN0YXRlID09ICJPUiIsICJQb3J0bGFuZCIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiQ2xhcmsiICYgU3RhdGUgPT0gIldBIiwgIlBvcnRsYW5kIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJTa2FtYW5pYSIgJiBTdGF0ZSA9PSAiV0EiLCAiUG9ydGxhbmQiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkRlbnZlciIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJBcmFwYWhvZSIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJKZWZmZXJzb24iICYgU3RhdGUgPT0gIkNPIiwgIkRlbnZlciIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiQWRhbXMiICYgU3RhdGUgPT0gIkNPIiwgIkRlbnZlciIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiRG91Z2xhcyIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJCcm9vbWZpZWxkIiAmIFN0YXRlID09ICJDTyIsICJEZW52ZXIiLCAgICANCiAgICBpZmVsc2UoQ291bnR5ID09ICJFbGJlcnQiICYgU3RhdGUgPT0gIkNPIiwgIkRlbnZlciIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiUGFyayIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJDbGVhciBDcmVlayIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJBbGFtZWRhIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiQ29udHJhIENvc3RhIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiTWFyaW4iICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJNb250ZXJleSIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIk5hcGEiICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJTYW4gQmVuaXRvIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FuIEZyYW5jaXNjbyIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBNYXRlbyIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbnRhIENsYXJhIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU2FudGEgQ3J1eiIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlNvbGFubyIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlNvbm9tYSIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLA0KICAgICAgICAgICBOQSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQ0KDQpkYXRhY2xlYW4gPC0gZGF0YWNsZWFuICU+JQ0KICBtdXRhdGUocmVnaW9uID0gDQogICAgaWZlbHNlKENvdW50eSA9PSAiS2luZ3MiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJRdWVlbnMiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJOZXcgWW9yayIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkJyb254IiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiUmljaG1vbmQiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJXZXN0Y2hlc3RlciIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkJlcmdlbiIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIkh1ZHNvbiIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlBhc3NhaWMiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJQdXRuYW0iICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJSb2NrbGFuZCIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlN1ZmZvbGsiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJOYXNzYXUiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJNaWRkbGVzZXgiICYgU3RhdGUgPT0gIk5KIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJNb25tb3V0aCIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIk9jZWFuIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU29tZXJzZXQiICYgU3RhdGUgPT0gIk5KIiwgIk5ldyBZb3JrIiwNCiAgICBpZmVsc2UoQ291bnR5ID09ICJFc3NleCIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLA0KICAgIGlmZWxzZShDb3VudHkgPT0gIlVuaW9uIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiTW9ycmlzIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiU3Vzc2V4IiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiSHVudGVyZG9uIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsDQogICAgaWZlbHNlKENvdW50eSA9PSAiUGlrZSIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLA0KICAgIHJlZ2lvbikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQ0KDQoNCiMgY29kZSBub3IgY2FsIHJlZ2lvbiBhcyBhbGwgb3RoZXJzIGluIENBIG5vdCBhbHJlYWR5IGRlZmluZWQNCg0KZGF0YWNsZWFuIDwtIGRhdGFjbGVhbiAlPiUNCiAgbXV0YXRlKHJlZ2lvbiA9IA0KICAgIGlmZWxzZShTdGF0ZSA9PSAiQ0EiICYgaXMubmEocmVnaW9uKSA9PSBUUlVFLCAiTm9yIENhbCIsIHJlZ2lvbikpDQoNCg0KI1JlbW92aW5nIENvbHVtbnMgdGhhdCBwcm92aWRlIG5vIGJlbmVmaXQgDQoNCmRhdGFjbGVhbiA8LSBzdWJzZXQoZGF0YWNsZWFuLHNlbGVjdCA9IC1jKEFzc2lnbm1lbnQuTnVtYmVyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuaGFzLkhpc3RvcmljYWwuTW5ncg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxTdWZmaXgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsQXNzaWdubWVudC5EYXRlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuTWFuYWdlcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50LlJvbGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsQXNzaWdubWVudC5UaXRsZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50LlN0YXR1cw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxTdHJhdGVneQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxQcm9ncmVzcy5MZXZlbA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50Lkdyb3VwDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuQ2F0ZWdvcnkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsRnVuZGluZy5NZXRob2QNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEV4cGVjdGVkLkJvb2suRGF0ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsUXVhbGlmaWNhdGlvbi5BbW91bnQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEV4cGVjdGVkLkJvb2suQW1vdW50DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxFeHBlY3RlZC5Cb29rLkRhdGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEhhcmQuR2lmdC5Ub3RhbA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsU29mdC5DcmVkaXQuVG90YWwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFRvdGFsLkFzc2lnbm1lbnQuR2lmdHMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLE5vLm9mLlBsZWRnZXMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFByb3Bvc2FsLi4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFByb3Bvc2FsLk5vdGVzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxISC5MaWZlLlNwb3VzZS5DcmVkaXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLExhc3QuQ29udGFjdC5CeS5NYW5hZ2VyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxYLi5vZi5Db250YWN0cy5CeS5NYW5hZ2VyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxEb25vclNlYXJjaC5SYW5nZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsaVdhdmUuUmFuZ2UNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFdlYWx0aEVuZ2luZS5SYW5nZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsUGhpbGFudGhyb3BpYy5Db21taXRtZW50cw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKQ0KI2NsZWFuaW5nIHVwIHppcCBjb2RlcyByZW1vdmluZyAtNCBhZnRlciANCmRhdGFjbGVhbiRaaXAgPC0gZ3N1YihkYXRhY2xlYW4kWmlwLCBwYXR0ZXJuPSItLioiLCByZXBsYWNlbWVudCA9ICIiKQ0KDQojYWRkaW5nIHppcCBjb2RlIGRhdGEgYW5kIGNvbHVtbiANCnppcCA8LSByZWFkLmNzdihoZXJlOjpoZXJlKCJmaW5hbF9wcm9qZWN0IiwgIlNhbGFyeV9aaXBjb2RlLmNzdiIpLA0KICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsDQogICAgICAgICAgICAgICAgIHN0cmlwLndoaXRlID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncyA9ICIiKQ0KDQoNCiNhZGRpbmcgemlwIHNhbGFyeSBjb2x1bW4NCmRhdGFjbGVhbiA8LWRhdGFjbGVhbiAlPiUNCiAgICBtdXRhdGUoemlwY29kZV9zbHJ5ID0gVkxPT0tVUChaaXAsIHppcCwgTkFNRSwgUzE5MDJfQzAzXzAwMkUpKQ0KDQojc2xyeSByYW5nZSANCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lDQogIG11dGF0ZSh6aXBzbHJ5X3JhbmdlID0gDQogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDEwMDAwOjg5OTk5LCAiOTBLLTk5SyIsDQogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDkwMDAwOjk5OTk5LCAiOTBLLTk5SyIsDQogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDEwMDAwMDoxNDk5OTksICIxMDBLLTE0OUsiLCANCiAgICBpZmVsc2UoemlwY29kZV9zbHJ5ICVpbiUgMTUwMDAwOjE5OTk5OSwgIjE1MEstMTk5SyIsDQogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDIwMDAwMDoyNDk5OTksICIyMDBLLTI0OUsiLA0KICAgIGlmZWxzZSh6aXBjb2RlX3NscnkgJWluJSAyNTAwMDA6Mjk5OTk5LCAiMjUwSy0yOTlLIiwNCiAgICBpZmVsc2UoemlwY29kZV9zbHJ5ICVpbiUgMzAwMDAwOjM0OTk5OSwgIjMwMEstMzQ5SyIsDQogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDM1MDAwMDozOTk5OTksICIzNTBLLTM5OUsiLA0KICAgIGlmZWxzZSh6aXBjb2RlX3NscnkgJWluJSA0MDAwMDA6NDk5OTk5LCAiNDAwSy00OTlLIiwNCiAgICBpZmVsc2UoemlwY29kZV9zbHJ5ICVpbiUgNTAwMDAwOjk5OTk5OSwgIjUwMEstOTk5SyIsDQogICAgTkEpKSkpKSkpKSkpKQ0KDQpzdW0oaXMubmEoZGF0YWNsZWFuJHppcGNvZGVfc2xyeSkpDQoNCiNhZGRpbmcgc2Nob2xhcnNoaXAgZGF0YSAoeS9uKQ0Kc2NobHIgPC0gcmVhZC5jc3YoaGVyZTo6aGVyZSgiZmluYWxfcHJvamVjdCIsICJzY2hvbGFyc2hpcC5jc3YiKSwNCiAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICBzdHJpcC53aGl0ZSA9IFRSVUUsDQogICAgICAgICAgICAgICAgIG5hLnN0cmluZ3MgPSAiIikNCg0KI2FkZGluZyBzY2hvbGFyc2hpcCBjb2x1bW4NCmRhdGFjbGVhbiA8LWRhdGFjbGVhbiAlPiUNCiAgICBtdXRhdGUoc2Nob2xhcnNoaXAgPSBWTE9PS1VQKElELCBzY2hsciwgSUQsIFNDSE9MQVJTSElQKSkgDQoNCiNyZXBsYWNpbmcgTkEgd2l0aCAwIA0KIGRhdGFjbGVhbiRzY2hvbGFyc2hpcCA8LSByZXBsYWNlX25hKGRhdGFjbGVhbiRzY2hvbGFyc2hpcCwnMCcpDQogDQojcmVwbGFjaW5nIFkgd2l0aCAxIA0KZGF0YWNsZWFuJHNjaG9sYXJzaGlwPC1pZmVsc2UoZGF0YWNsZWFuJHNjaG9sYXJzaGlwPT0iWSIsMSwwKQ0KDQojY2hlY2tpbmcgaG93IG1hbnkgYXJlIE4NCnRhYmxlKGRhdGFjbGVhbiRzY2hvbGFyc2hpcCkNCg0KDQojY2hlY2tpbmcgYW5kIGRlbGV0aW5nIHNjaG9sYXJzaGlwIGNvbHVtbiANCmNsYXNzKGRhdGFjbGVhbiRzY2hscl9mY3QpDQpkYXRhY2xlYW4gPSBzdWJzZXQoZGF0YWNsZWFuLCBzZWxlY3QgPSAtYyhzY2hvbGFyc2hpcCkpDQogIA0KI2NoZWNraW5nIGZvciBkdXBsaWNhdGVzIE4gPjEgaW5kaWNhdGVzIGEgcmVjb3JkcyB2YWx1ZXMgYXJlIGluIHRoZSBmaWxlIHR3aWNlIA0KZGF0YWNsZWFuICU+JSBncm91cF9ieShJRCkgJT4lIGNvdW50KCkgJT4lIGFycmFuZ2UoZGVzYyhuKSkNCg0KI3JlbW92aW5nIGR1cGxpY2F0ZWQgcmVjb3Jkcw0KDQpkYXRhY2xlYW4gPC0gdW5pcXVlKGRhdGFjbGVhbikNCg0KI24gPSAxIG5vIElEIHdpdGggbXVsdGlwbGUgcmVjb3JkcyBjbGVhbmVkIG9mIGR1cGVzDQpkYXRhY2xlYW4gJT4lIGdyb3VwX2J5KElEKSAlPiUgY291bnQoKSAlPiUgYXJyYW5nZShkZXNjKG4pKQ0KDQpgYGANCg0KDQoxZCBDcmVhdGluZyBtYW55IG1hbnkgZmFjdG9yIHZhcmlhYmxlcw0KDQpgYGB7cn0NCg0KZGF0YWNsZWFuIDwtIA0KICBkYXRhY2xlYW4gJT4lIA0KICAjU0VYDQogIG11dGF0ZShzZXhfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShTZXgpLA0Kc2V4X3NpbXBsZSA9IA0KICAgIGZjdF9sdW1wX24oU2V4LCBuID0gMiksDQojTUFSUklFRA0KbWFycmllZF9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKE1hcnJpZWQpLA0KICAjRE9OT1IgU0VHTUVOVA0KICBkb25vcnNlZ19mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKERvbm9yLlNlZ21lbnQpLA0KICAgICAgICAgZG9ub3JzZWdfc2ltcGxlID0gDQogICAgICAgICAgIGZjdF9sdW1wX24oRG9ub3IuU2VnbWVudCwgbiA9IDQpLA0KICAjQ09OVEFDVCBSVUxFDQogICAgICAgICBjb250YWN0X2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ29udGFjdC5SdWxlcyksDQogICAgICAgICBjb250YWN0X3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKENvbnRhY3QuUnVsZXMsIG4gPSA0KSwNCiAgI1NQT1VTRSBNQUlMDQogICAgICAgICBzcG9tYWlsX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoU3BvdXNlLk1haWwuUnVsZXMpLA0KICAgICAgICAgc3BvbWFpbF9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihTcG91c2UuTWFpbC5SdWxlcywgbiA9IDQpLA0KICAjSk9CIFRJVExFDQogICAgICAgICBqb2J0aXRsZV9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKEpvYi5UaXRsZSksDQogICAgICAgICBqb2J0aXRsZV9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihKb2IuVGl0bGUsIG4gPSAxMCksDQogICNERUdSRUUgVFlQRSAxDQogICAgICAgICBkZWcxX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoRGVncmVlLlR5cGUuMSksDQogICAgICAgICBkZWcxX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKERlZ3JlZS5UeXBlLjEsIG4gPSAxMCksDQogICNERUdSRUUgVFlQRSAyDQogICAgICAgICBkZWcyX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoRGVncmVlLlR5cGUuMiksDQogICAgICAgICBkZWcyX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKERlZ3JlZS5UeXBlLjIsIG4gPSAxMCksDQogICNNQUpPUiAxDQogICAgICAgICBtYWoxX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWFqb3IuMSksDQogICAgICAgICBtYWoxX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKE1ham9yLjEsIG4gPSAxMCksDQogICNNQUpPUiAyDQogICAgICAgICBtYWoyX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWFqb3IuMiksDQogICAgICAgICBtYWoyX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKE1ham9yLjIsIG4gPSAxMCksDQogICNNSU5PUiAxDQogICAgICAgICBtaW4xX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWlub3IuMSksDQogICAgICAgICBtaW4xX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKE1pbm9yLjEsIG4gPSA1KSwNCiAgI01JTk9SIDINCiAgICAgICAgIG1pbjJfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShNaW5vci4yKSwNCiAgICAgICAgIG1pbjJfc2ltcGxlID0gDQogICAgICAgICAgIGZjdF9sdW1wX24oTWlub3IuMiwgbiA9IDUpLA0KICAjU0NIT09MIDENCiAgICAgICAgIHNjaG9vbDFfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShTY2hvb2wuMSksDQogICAgICAgICBzY2hvb2wxX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKFNjaG9vbC4xLCBuID0gMTApLA0KICAjU0NIT09MIDINCiAgICAgICAgIHNjaG9vbDJfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShTY2hvb2wuMiksDQogICAgICAgICBzY2hvb2wyX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKFNjaG9vbC4yLCBuID0gMTApLA0KICAjSU5TVElUVVRJT04gVFlQRQ0KICAgICAgICAgaW5zdHR5cGVfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShJbnN0aXR1dGlvbi5UeXBlKSwNCiAgICAgICAgIGluc3R0eXBlX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKEluc3RpdHV0aW9uLlR5cGUsIG4gPSA0KSwNCiAgI0VYVFJBQ1VSUklDVUxBUg0KICAgICAgICAgZXh0cmFfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShFeHRyYWN1cnJpY3VsYXIpLA0KICAgICAgICAgZXh0cmFfc2ltcGxlID0gDQogICAgICAgICAgIGZjdF9sdW1wX24oRXh0cmFjdXJyaWN1bGFyLCBuID0gMTApLA0KICAjSEggRklSU1QgR0lGVCBGVU5EDQogICAgICAgICBoaGZpcnN0Z2lmdF9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKEhILkZpcnN0LkdpZnQuRnVuZCksDQogICAgICAgICBoaGZpcnN0Z2lmdF9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihISC5GaXJzdC5HaWZ0LkZ1bmQsIG4gPSAxMCksDQojQ0hJTEQgMSBFTlJPTEwgU1RBVFVTDQogICAgICAgICBjaDFfZW5yb2xsX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMS5FbnJvbGwuU3RhdHVzKSwNCiAgICAgICAgIGNoMV9lbnJvbGxfc2ltcGxlID0gDQogICAgICAgICAgIGZjdF9sdW1wX24oQ2hpbGQuMS5FbnJvbGwuU3RhdHVzLCBuID0gNCksDQojQ0hJTEQgMSBNQUpPUg0KICAgICAgICAgY2gxX21hal9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjEuTWFqb3IpLA0KICAgICAgICAgY2gxX21hal9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4xLk1ham9yLCBuID0gNCksDQojQ0hJTEQgMSBNSU5PUg0KICAgICAgICAgY2gxX21pbl9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjEuTWlub3IpLA0KICAgICAgICAgY2gxX21pbl9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4xLk1pbm9yLCBuID0gNCksDQojQ0hJTEQgMSBTQ0hPT0wNCiAgICAgICAgIGNoMV9zY2hvb2xfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShDaGlsZC4xLlNjaG9vbCksDQogICAgICAgICBjaDFfc2Nob29sX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjEuU2Nob29sLCBuID0gNCksDQojQ0hJTEQgMSBGRUVERVINCiAgICAgICAgIGNoMV9mZWVkZXJfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShDaGlsZC4xLkZlZWRlci5TY2hvb2wpLA0KICAgICAgICAgY2gxX2ZlZWRlcl9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4xLkZlZWRlci5TY2hvb2wsIG4gPSA0KSwNCiNDSElMRCAyIEVOUk9MTCBTVEFUVVMNCiAgICAgICAgIGNoMV9lbnJvbGxfZmN0ID0gDQogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShDaGlsZC4yLkVucm9sbC5TdGF0dXMpLA0KICAgICAgICAgY2gyX2Vucm9sbF9zaW1wbGUgPSANCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4yLkVucm9sbC5TdGF0dXMsIG4gPSA0KSwNCiNDSElMRCAyIE1BSk9SDQogICAgICAgICBjaDJfbWFqX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMi5NYWpvciksDQogICAgICAgICBjaDJfbWFqX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjIuTWFqb3IsIG4gPSA0KSwNCiNDSElMRCAyIE1JTk9SDQogICAgICAgICBjaDJfbWluX2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMi5NaW5vciksDQogICAgICAgICBjaDJfbWluX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjIuTWlub3IsIG4gPSA0KSwNCiNDSElMRCAyIFNDSE9PTA0KICAgICAgICAgY2gyX3NjaG9vbF9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjIuU2Nob29sKSwNCiAgICAgICAgIGNoMl9zY2hvb2xfc2ltcGxlID0gDQogICAgICAgICAgIGZjdF9sdW1wX24oQ2hpbGQuMi5TY2hvb2wsIG4gPSA0KSwNCiNDSElMRCAyIEZFRURFUg0KICAgICAgICAgY2gyX2ZlZWRlcl9mY3QgPSANCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjIuRmVlZGVyLlNjaG9vbCksDQogICAgICAgICBjaDJfZmVlZGVyX3NpbXBsZSA9IA0KICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjIuRmVlZGVyLlNjaG9vbCwgbiA9IDQpLA0KDQogICAgKQ0KDQoNCg0KI2NoZWNraW5nIHRvIHNlZSBpZiBpdHMgYSBmYWN0b3INCiNjbGFzcyhkYXRhY2xlYW4kc2V4X2ZjdCkNCiNjbGFzcyhkYXRhY2xlYW4kZG9ub3JzZWdfZmN0KQ0KI2NsYXNzKGRhdGFjbGVhbiRjb250YWN0X2ZjdCkNCiNjbGFzcyhkYXRhY2xlYW4kc3BvbWFpbF9mY3QpDQoNCiNjaGVja2luZyBsZXZlbHMNCiNsZXZlbHMoZGF0YWNsZWFuJHNleF9zaW1wbGUpDQojbGV2ZWxzKGRhdGFjbGVhbiRkb25vcnNlZ19zaW1wbGUpDQojbGV2ZWxzKGRhdGFjbGVhbiRjb250YWN0X3NpbXBsZSkNCiNsZXZlbHMoZGF0YWNsZWFuJHNwb21haWxfc2ltcGxlKQ0KI2xldmVscyhkYXRhY2xlYW4kaGhmaXJzdGdpZnRfc2ltcGxlKQ0KDQojY3JlYXRpbmcgYSB0YWJsZSBhZ2FpbnN0IFNleCBjb2x1bW4gDQojdGFibGUoZGF0YWNsZWFuJHNleF9mY3QsIGRhdGFjbGVhbiRzZXhfc2ltcGxlKQ0KDQoNCmBgYA0KDQoNCg0KRG9ub3JTZWdtZW50IEFuYWx5c2lzDQoNCmBgYHtyfQ0KI2dyb3VwaW5nIGJ5IGRvbm9yc2VnbWVudCBhbmQgYW5hbHl6aW5nIA0KZGF0YWNsZWFuICU+JQ0KICBncm91cF9ieShEb25vci5TZWdtZW50KSAlPiUNCiAgc3VtbWFyaXNlKENvdW50ID0gbGVuZ3RoKERvbm9yLlNlZ21lbnQpLA0KICAgICAgICAgICAgbWVhbl90b3RhbF9naXYgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZykpICU+JQ0KICBhcnJhbmdlKC1Db3VudCkgJT4lDQogIGZpbHRlcihDb3VudCA+PSAxMDApICU+JQ0KICAjYWRkZWQgc2NhbGVzIHBhY2thZ2UgdG8gaGF2ZSB0aGUgdmFsdWVzIHNob3cgaW4gZG9sbGFyIA0KICBtdXRhdGUobWVhbl90b3RhbF9naXYgPSBkb2xsYXIobWVhbl90b3RhbF9naXYpKSAlPiUNCiAga2FibGUoY29sLm5hbWVzID0gYygiRG9ub3IgU2VnbWVudCIsICJDb3VudCIsICJNZWFuIEhIIExpZmV0aW1lIEdpdmluZyIpLCBhbGlnbj1yZXAoJ2MnLCAzKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEYpDQogIA0KDQpgYGANCg0KRmlyc3QgZ2lmdCBzaXplIA0KYGBge3J9DQphcSA8LSBxdWFudGlsZShkYXRhY2xlYW4kSEguRmlyc3QuR2lmdC5BbW91bnQsIHByb2JzID0gYyguMjUsLjUwLC43NSwuOSwuOTkpLCBuYS5ybSA9IFRSVUUpDQoNCmFxIDwtIGFzLmRhdGEuZnJhbWUoYXEpDQoNCmFxJGFxIDwtIGRvbGxhcihhcSRhcSkNCg0KYXEgJT4lDQogIGthYmxlKGNvbC5uYW1lcyA9ICJRdWFudGlsZSIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGKQ0KICANCg0KYGBgDQpDb25zZWN1dGl2ZSBnaXZpbmcNCmBgYHtyfQ0KI2NvbnNlY3V0aXZlIHllYXJzIG9mIGdpdmluZyANCmRhdGFjbGVhbiAlPiUNCiAgZmlsdGVyKE1heC5Db25zZWMuRmlzY2FsLlllYXJzID4gMCkgJT4lDQogIGdncGxvdChhZXMoTWF4LkNvbnNlYy5GaXNjYWwuWWVhcnMpKSArIGdlb21faGlzdG9ncmFtKGZpbGwgPSAiIzAwMjg0NSIsIGJpbnMgPSAyMCkgKyANCiAgdGhlbWVfZWNvbm9taXN0X3doaXRlKCkgKw0KICBnZ3RpdGxlKCJDb25zZWN1dGl2ZSBZZWFycyBvZiBHaXZpbmcgRGlzdHJpYnV0aW9uIikgKyANCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTIwLDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAwMDAwMCw1MDAwKSkgDQoNCg0KDQpgYGANCg0KTGlmZXRpbWUgZ2l2aW5nIGJhc2VkIG9uIG51bWJlciBvZiBjaGlsZHJlbiANCg0KYGBge3J9DQpkYXRhY2xlYW4gJT4lDQogIGZpbHRlcihISC5MaWZldGltZS5HaXZpbmcgPD0gMTAwMDApICU+JQ0KICBmaWx0ZXIoSEguTGlmZXRpbWUuR2l2aW5nID4gMCkgJT4lDQogIG11dGF0ZShgTm9fb2ZfQ2hpbGRyZW5gID0gYXMuZmFjdG9yKGBOb19vZl9DaGlsZHJlbmApKSAlPiUNCiAgZ2dwbG90KGFlcyhISC5MaWZldGltZS5HaXZpbmcsIGZpbGwgPSBgTm9fb2ZfQ2hpbGRyZW5gKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzApICsgdGhlbWVfZWNvbm9taXN0X3doaXRlKCkgKw0KICB4bGFiKE5VTEwpICsgeWxhYihOVUxMKSArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAwMDAsMTAwMCkpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwMDAwMDAwMCw1MDAwKSkgKw0KICBnZ3RpdGxlKCJHaXZpbmcgZGlzdHJpYnV0aW9uIGFuZCBudW1iZXIgb2YgY2hpbGRyZW4iKSsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMDAyODQ1IiwgIiMwMGNmY2MiLCAiI2ZmOTk3MyIpKQ0KDQoNCg0KYGBgDQoNCg0KTWVhbiwgTWVkaWFuLCBhbmQgQ291bnQgb2YgR2l2aW5nIGluIEFnZSBSYW5nZXMgDQoNCmBgYHtyfQ0KDQphZ2VfcmFuZ2VfZ2l2aW5nIDwtIGRhdGFjbGVhbiAlPiUNCiAgZ3JvdXBfYnkoYWdlX3JhbmdlKSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19naXZpbmcgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lZF9naXZpbmcgPSBtZWRpYW4oSEguTGlmZXRpbWUuR2l2aW5nLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgYW1vdW50X29mX3Blb3BsZV9pbl9hZ2VfcmFuZ2UgPSBuKCkpDQoNCg0KZ2xpbXBzZShhZ2VfcmFuZ2VfZ2l2aW5nKQ0KDQpgYGANCg0KDQoNCg0KDQojIyBQYXJ0IDINCg0KMmEpIFBsb3R0aW5nIGF2ZXJhZ2UgZ2l2aW5nIGJ5IGFnZSByYW5nZSANCg0KDQpgYGB7cn0NCg0KYWdlX3JhbmdlX2dpdmluZyA8LQ0KICBhZ2VfcmFuZ2VfZ2l2aW5nICU+JQ0KICBtdXRhdGUoYWdlX3JhbmdlID0gZmFjdG9yKGFnZV9yYW5nZSkpDQoNCmdncGxvdChhZ2VfcmFuZ2VfZ2l2aW5nLCBhZXMoYWdlX3JhbmdlLCBhdmdfZ2l2aW5nKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0PTEpKQ0KDQoNCmBgYA0KDQoNCjJiKSBDb3VudCBvZiBkb25vcnMgYmFzZWQgb24gYWdlIHJhbmdlIChhbm90aGVyIHdheSB0byBsb29rIGF0IGl0KQ0KDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QoZGF0YWNsZWFuLCANCiAgICAgICBhZXMoYWdlX3JhbmdlKSkgKyANCiAgICAgICBnZW9tX2JhcigpICsgDQogICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3Q9MSkpICsgDQogIGxhYnModGl0bGUgPSAiQ291bnQgb2YgQWdlIFJhbmdlcyIsIHggPSAiIiwgeSA9ICIiKQ0KICANCg0KYGBgDQoNCjJjKSBCb3hwbG90IG9mIHRoZSBBZ2UgUmFuZ2VzIEFnYWluc3QgdGhlIExpZmV0aW1lIEdpdmluZyBBbW91bnRzIHdpdGggYSBsb2cgc2NhbGUgYXBwbGllZCAtIHRoZSByZWFzb24gd2UgYXBwbGllZCBsb2cgc2NhbGUgaXMgdG8gcmVzb2x2ZSBpc3N1ZXMgd2l0aCB2aXN1YWxpemF0aW9ucyB0aGF0IHNrZXcgdG93YXJkcyBsYXJnZSB2YWx1ZXMgaW4gb3VyIGRhdGFzZXQuIA0KDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QoZGF0YWNsZWFuLCBhZXMoYWdlX3JhbmdlLEhILkxpZmV0aW1lLkdpdmluZyxmaWxsID0gYWdlX3JhbmdlKSkgKyANCiAgZ2VvbV9ib3hwbG90KA0KICBvdXRsaWVyLmNvbG91ciA9ICJyZWQiKSArIA0KICBzY2FsZV95X2xvZzEwKCkgKw0KICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpDQogIA0KDQpgYGANCg0KMmQpIFNwbGl0dGluZyBieSBhZ2UgYW5kIGdlbmRlciANCg0KDQpgYGB7cn0NCg0KDQojY3JlYXRpbmcgYm94cGxvdHMgDQpkYXRhY2xlYW4gJT4lIA0KICBmaWx0ZXIoQWdlIDwgMTAwKSAlPiUgI3JlbW92aW5nIHRoZSB3ZWlyZCBvdXRsaWVycyB0aGF0IGFyZSBvdmVyIDEwMCANCiAgZmlsdGVyKFNleCAlaW4lIGMoIk0iLCAiRiIpKSAlPiUNCiAgZ2dwbG90KGFlcyhTZXgsIEFnZSkpICsgDQogIGdlb21fYm94cGxvdCgpICsgDQogIHRoZW1lX2Vjb25vbWlzdCgpICsgDQogIGdndGl0bGUoIkFnZXMgb2YgRG9ub3JzIEJhc2VkIG9uIEdlbmRlciIpICsgDQogIHhsYWIoTlVMTCkgKyB5bGFiKE5VTEwpDQogIA0KDQpgYGANCkdpdmluZyBieSBnZW5kZXINCg0KDQpgYGB7cn0NCg0KI3JlbW92ZSBOQXMgVSBYIA0KcSA8LSBnZ3Bsb3QoZGF0YWNsZWFuKQ0KcSArIHN0YXRfc3VtbWFyeV9iaW4oDQogIGFlcyh5ID0gSEguTGlmZXRpbWUuR2l2aW5nLCB4ID0gc2V4X3NpbXBsZSksIA0KICBmdW4ueSA9ICJtZWFuIiwgZ2VvbSA9ICJiYXIiKQ0KDQpzdW1tYXJ5KGRhdGFjbGVhbiRzZXhfc2ltcGxlKQ0KDQpgYGANCg0KTWVhbiBhZ2UgYnkgZ2VuZGVyDQoNCg0KYGBge3J9DQojYnJlYWtkb3duIG9mIHNleHMgDQp0YWxseShncm91cF9ieShkYXRhY2xlYW4sIFNleCkpDQoNCnN1bW1hcml6ZShncm91cF9ieShkYXRhY2xlYW4sIFNleCksIA0KICAgICAgICAgIGF2Z19naXZpbmcgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICBhdmdfYWdlID0gbWVhbihBZ2UsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgbWVkX2FnZSA9IG1lZGlhbihBZ2UsIG5hLnJtID0gVFJVRSkpDQoNCiNncm91cGluZyBieSBzZXggYW5kIGFnZSByYW5nZSBmb3Igc2xpZGVzIA0KdGFsbHkoZ3JvdXBfYnkoZGF0YWNsZWFuLCBTZXgsIGFnZV9yYW5nZSkpDQoNCg0KDQpgYGANCg0KDQoNCjJlKSBEaXN0cmlidXRpb24gb2YgcGVvcGxlIGluIHRoZSBzdGF0ZXMgdGhhdCB0aGV5IGxpdmUuDQoNCmBgYHtyfQ0KDQogIGRhdGFjbGVhbiAlPiUNCiAgbXV0YXRlKFN0YXRlID0gaWZlbHNlKFN0YXRlID09ICIgIiwgIk5BIiwgU3RhdGUpKSAlPiUNCiAgZmlsdGVyKFN0YXRlICE9ICJOQSIpICU+JQ0KICBncm91cF9ieShTdGF0ZSkgJT4lDQogIHN1bW1hcmlzZShDb3VudCA9IGxlbmd0aChTdGF0ZSkpICU+JQ0KICBmaWx0ZXIoQ291bnQgPiA4MDApICU+JQ0KICBhcnJhbmdlKC1Db3VudCkgJT4lDQogIGthYmxlKGNvbC5uYW1lcyA9IGMoIkRvbm9yJ3MgU3RhdGUiLCAiQ291bnQiKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiKSwNCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikNCiAgDQogDQogIA0KICANCg0KDQpgYGANCg0KMmYpIExvb2tpbmcgYXQgYWxsIGRvbm9ycyBmaXJzdCBnaWZ0IGFtb3VudC4gNzUlIG1hZGUgYSBmaXJzdCBnaWZ0IG9mIDwxMDAuIA0KDQpgYGB7cn0NCg0KIG5vX25vbl9kb25vcnMgPC0gZGF0YWNsZWFuICU+JQ0KICBmaWx0ZXIoTGlmZXRpbWUuR2l2aW5nICE9IDApDQogIA0KbmQgPC0gcXVhbnRpbGUobm9fbm9uX2Rvbm9ycyRISC5GaXJzdC5HaWZ0LkFtb3VudCwgcHJvYnMgPSBjKC4yNSwuNTAsLjc1LC45LC45OSksIG5hLnJtID0gVFJVRSkNCg0KbmQgPC0gYXMuZGF0YS5mcmFtZShuZCkNCg0KbmQgJT4lDQogIGthYmxlKGNvbC5uYW1lcyA9ICJRdWFudGlsZSIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGKQ0KICANCiAgDQoNCg0KYGBgDQoNCg0KDQojIyBNb2RlbGluZyBmb3IgeW91IA0KDQpTcGxpdCBkYXRhDQoNCmBgYCB7cn0NCiNjb252ZXJ0aW5nIG1hcnJpZWQgWSBhbmQgTiB0byAxIGFuZCAwIA0KZGF0YWNsZWFuIDwtIGRhdGFjbGVhbiAlPiUNCiAgICAgIG11dGF0ZShNYXJyaWVkX3NpbXBsZSA9IGlmZWxzZShNYXJyaWVkID09ICJOIiwwLDEpKQ0KDQpkYXRhY2xlYW4gPC0gZGF0YWNsZWFuICU+JQ0KICBtdXRhdGUoaGgubGlmZXRpbWUuZ2l2aW5nX2ZjdCA9IGFzLmZhY3RvcihISC5MaWZldGltZS5HaXZpbmcpKQ0KDQoNCmxpYnJhcnkoInJzYW1wbGUiKQ0KDQpkYXRhX3NwbGl0IDwtIGluaXRpYWxfc3BsaXQoZGF0YWNsZWFuLCBwcm9wID0gMC43NSkNCg0KZGF0YV90cmFpbiA8LSB0cmFpbmluZyhkYXRhX3NwbGl0KQ0KZGF0YV90ZXN0IDwtIHRlc3RpbmcoZGF0YV9zcGxpdCkNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCnAgPC0gZGF0YWNsZWFuICU+JQ0KICBnZ3Bsb3QoYWVzKEFnZSkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucz0zMCwgZmlsbCA9ICJibHVlIikgKyB0aGVtZV9lY29ub21pc3Rfd2hpdGUoKSArDQogIGdndGl0bGUoIk92ZXJhbGwgRG9ub3IgQWdlIERpc3RyaWJ1dGlvbiIpICsgDQogIHhsYWIoTlVMTCkgKyB5bGFiKE5VTEwpICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSg1LDEwMCxieSA9IDIwKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwLDEwMCxieSA9IDIwKSkgKyB4bGltKGMoMjAsMTAwKSkNCg0KZ2dwbG90bHkocCkNCiAgDQpwDQoNCmdncGxvdChkYXRhID0gZGF0YWNsZWFuLCBhZXMoeCA9IEFnZSkpICsgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ImJsdWUiKSsgeGxpbShjKDIwLDEwMCkpDQoNCiAgDQoNCg0KYGBgDQoNCkFub3RoZXIgSGlzdG9ncmFtDQoNCg0KYGBge3J9DQoNCmRhdGFjbGVhbiAlPiUNCiAgZmlsdGVyKEFnZSA+PSAxMCkgJT4lDQogIGZpbHRlcihBZ2UgPD0gOTApICU+JQ0KICBnZ3Bsb3QoYWVzKEFnZSkpICsgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICIjMDAyODQ1IiwgYmlucyA9IDIwKSArIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsNCiAgZ2d0aXRsZSgiT3ZlcmFsbCBEb25vciBBZ2UgRGlzdHJpYnV0aW9uIikgKyANCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTIwLDUpKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAwMDAwMCwyMDAwKSkgDQoNCmBgYA0KQWdlIGRpc3RyaWJ1dGlvbiBieSBnZW5kZXIgDQoNCmBgYHtyfQ0KI0FnZSBHZW5kZXIgZmlsdGVyZWQgb3V0IGJlbG93IDE1IGFuZCBhYm92ZSA5MCAtIGFsc28gcmVtb3ZlZCBVIFggdGhlIHdlaXJkIHZhbHVlcyANCmRhdGFjbGVhbiAlPiUNCiAgZmlsdGVyKEFnZSA+PSAxNSkgJT4lDQogIGZpbHRlcihBZ2UgPD0gOTApICU+JQ0KICBtdXRhdGUoU2V4ID0gYXMuZmFjdG9yKFNleCkpICU+JQ0KICBmaWx0ZXIoU2V4ICE9ICJVIikgJT4lDQogIGZpbHRlcihTZXggIT0gIlgiKSAlPiUNCiAgZ2dwbG90KGFlcyhBZ2UsIGZpbGwgPSBTZXgpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAyNSkgKyB0aGVtZV9lY29ub21pc3Rfd2hpdGUoKSArDQogIGdndGl0bGUoIkFnZSBEaXN0cmlidXRpb24gYnkgR2VuZGVyIikgKyANCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTIwLDEwKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsNTAwMDAsMjAwMCkpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNmZjk5NzMiLCAiIzAwY2ZjYyIpKQ0KYGBgDQoNCkRvbm9yIGFnZSBkaXN0cmlidXRpb24gYnkgbWFyaXRhbCBzdGF0dXMgDQoNCmBgYHtyfQ0KI0FnZSBNYXJpdGFsIFN0YXR1cw0KZGF0YWNsZWFuICU+JQ0KICBmaWx0ZXIoQWdlID49IDIwKSAlPiUNCiAgZmlsdGVyKEFnZSA8PSA4NSkgJT4lDQogIGdncGxvdChhZXMoQWdlLCBmaWxsID0gTWFycmllZCkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDI1KSArIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsNCiAgZ2d0aXRsZSgiT3ZlcmFsbCBEb25vciBBZ2UgRGlzdHJpYnV0aW9uIGJ5IE1hcml0YWwgU3RhdHVzIikgKyANCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTIwLDUpKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw1MDAwMCwyMDAwKSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI2ZmOTk3MyIsICIjMDBjZmNjIikpDQpgYGANCg0KTGluZWFyIE1vZGVsIA0KDQpgYGB7cn0NCiNUaGVzZSB3aWxsIGZvY3VzIG9uIHByZWRpY3Rpbmcgd2hldGhlciBhIGNvbnN0aXR1ZW50IGlzIGEgZG9ub3Igb3Igbm9uLWRvbm9yLiANCg0KDQoNCm1vZDFsbSA8LSBsbSggTGlmZXRpbWUuR2l2aW5nIH4gTWFycmllZF9zaW1wbGUsDQogICAgICAgICAgIGRhdGEgPSBkYXRhY2xlYW4pDQoNCm1vZDJsbSA8LSBsbSggVG90YWwuR2l2aW5nLlllYXJzIH4gTGlmZXRpbWUuR2l2aW5nLA0KICAgICAgICAgICBkYXRhID0gZGF0YWNsZWFuKQ0KDQpzdW1tYXJ5KG1vZDFsbSkNCnN1bW1hcnkobW9kMmxtKQ0KI2luY3JlYXNpbmcgdGhlIGdpdmluZyB5ZWFyIG9uZSB5ZWFyIGluY3JlYXNlIHRvdGFsIGdpdmluZyBieSAwLjAwMzUNCg0KDQpnZ3Bsb3QoZGF0YSA9IGRhdGFfdHJhaW4sIGFlcyh4ID0gQWdlLCB5ID0gbG9nKEhILkxpZmV0aW1lLkdpdmluZykpKSArIGdlb21fcG9pbnQoYWxwaGEgPSAxLzEwKSArIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKSArIGZhY2V0X3dyYXAofmRvbm9yc2VnX2ZjdCkgKyB0aGVtZV9jbGVhbihiYXNlX3NpemUgPSA4KSArIGxhYnMoeCA9ICJYIiwgeSA9ICJZIikgKw0KICAgICAgZ2d0aXRsZSgiVGl0bGUiKQ0KDQoNCg0KZ2dwbG90KGRhdGEgPSBkYXRhX3RyYWluLCBhZXMoeCA9IEhILkZpcnN0LkdpZnQuQW1vdW50LCB5ID0gVG90YWwuR2l2aW5nLlllYXJzKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMS8xMCkgKyBnZW9tX3Ntb290aChtZXRob2QgPSBsbSkgKyBmYWNldF93cmFwKH5kb25vcnNlZ19mY3QpICsgdGhlbWVfY2xlYW4oYmFzZV9zaXplID0gOCkgKyBsYWJzKHggPSAiWCIsIHkgPSAiWSIpICsNCiAgICAgIGdndGl0bGUoIlRpdGxlIikNCg0KDQpgYGANCg0KDQoNCk1PUkUgTU9ERUxTDQoNCkJpZyBsb2dpc3RpYyBtb2RlbA0KDQpgYGB7cn0NCg0KIyBTZXQgZmFtaWx5IHRvIGJpbm9taWFsIHRvIHNldCBsb2dpc3RpYyBmdW5jdGlvbg0KIyBSdW4gdGhlIG1vZGVsIG9uIHRoZSB0cmFpbmluZyBzZXQNCg0KZG9ub3JfbG9naXQxIDwtDQogIGdsbShoaC5saWZldGltZS5naXZpbmdfZmN0IH4gTWFycmllZF9zaW1wbGUsDQogICAgICBmYW1pbHkgPSAiYmlub21pYWwiLA0KICAgICAgZGF0YSA9IGRhdGFfdHJhaW4pDQoNCnN1bW1hcnkoZG9ub3JfbG9naXQxKQ0KDQoNCmRvbm9yX2xvZ2l0MiA8LQ0KICBnbG0oaGgubGlmZXRpbWUuZ2l2aW5nX2ZjdCB+IE5vX29mX0NoaWxkcmVuLA0KICAgICAgZmFtaWx5ID0gImJpbm9taWFsIiwNCiAgICAgIGRhdGEgPSBkYXRhX3RyYWluKQ0KDQpzdW1tYXJ5KGRvbm9yX2xvZ2l0MikNCg0KDQoNCg0KDQoNCg0KI3N1bW1hcnkoZGF0YV90cmFpbiRtYWpvcl9naWZ0ZXIpDQoNCmRvbm9yX2xvZ2l0MyA8LQ0KICBnbG0obWFqb3JfZ2lmdGVyIH4gTWFycmllZF9zaW1wbGUgKyBOb19vZl9DaGlsZHJlbiArIE1hcnJpZWRfc2ltcGxlICsgQXNzaWdubWVudF9mbGFnICsgVG90YWwuR2l2aW5nLlllYXJzLA0KICAgICAgZmFtaWx5ID0gImJpbm9taWFsIiwNCiAgICAgIGRhdGEgPSBkYXRhX3RyYWluKQ0KDQpzdW1tYXJ5KGRvbm9yX2xvZ2l0MykNCmV4cChkb25vcl9sb2dpdDMkY29lZmZpY2llbnRzKQ0KDQojdHJhaW5pbmcgcHJlZGljdGlvbnMgZm9yIGluIHNhbXBsZSBwcmVkcyANCnByZWRzX3RyYWluIDwtIHByZWRpY3QoZG9ub3JfbG9naXQzLCBuZXdkYXRhID0gZGF0YV90cmFpbiwgdHlwZSA9ICJyZXNwb25zZSIpIA0KDQojdGVzdCBwcmVkaWN0cyBmb3IgT09TIChvdXQgb2Ygc2FtcGxlKQ0KcHJlZHNfdGVzdCA8LSBwcmVkaWN0KGRvbm9yX2xvZ2l0MywgbmV3ZGF0YSA9IGRhdGFfdGVzdCwgdHlwZSA9ICJyZXNwb25zZSIpDQoNCmhlYWQocHJlZHNfdHJhaW4pDQpoZWFkKHByZWRzX3Rlc3QpDQoNCg0KDQpyZXN1bHRzX3RyYWluIDwtIGRhdGEuZnJhbWUoDQogIGB0cnV0aGAgPSBkYXRhX3RyYWluICAgJT4lIHNlbGVjdChtYWpvcl9naWZ0ZXIpICU+JSANCiAgICBtdXRhdGUobWFqb3JfZ2lmdGVyID0gYXMubnVtZXJpYyhtYWpvcl9naWZ0ZXIpKSwNCiAgYENsYXNzMWAgPSAgcHJlZHNfdHJhaW4sDQogIGB0eXBlYCA9IHJlcCgidHJhaW4iLGxlbmd0aChwcmVkc190cmFpbikpDQopDQoNCnJlc3VsdHNfdGVzdCA8LSBkYXRhLmZyYW1lKA0KICBgdHJ1dGhgID0gZGF0YV90ZXN0ICAgJT4lIHNlbGVjdChtYWpvcl9naWZ0ZXIpICU+JSANCiAgICBtdXRhdGUobWFqb3JfZ2lmdGVyID0gYXMubnVtZXJpYyhtYWpvcl9naWZ0ZXIpKSwNCiAgYENsYXNzMWAgPSAgcHJlZHNfdGVzdCwNCiAgYHR5cGVgID0gcmVwKCJ0ZXN0IixsZW5ndGgocHJlZHNfdGVzdCkpDQopDQoNCnJlc3VsdHMgPC0gYmluZF9yb3dzKHJlc3VsdHNfdHJhaW4scmVzdWx0c190ZXN0KQ0KDQpkaW0ocmVzdWx0c190cmFpbikNCmRpbShyZXN1bHRzX3Rlc3QpDQpkaW0ocmVzdWx0cykNCg0KbGlicmFyeSgncGxvdFJPQycpDQoNCnBfcGxvdCA8LQ0KICBnZ3Bsb3QocmVzdWx0cywNCiAgICAgICAgIGFlcyhtID0gQ2xhc3MxLCBkID0gbWFqb3JfZ2lmdGVyLCBjb2xvciA9IHR5cGUpKSArDQogIGdlb21fcm9jKGxhYmVsc2l6ZSA9IDIuNSwNCiAgICAgICAgICAgI1Rvb2sgdGhlIGxhYmVsc2l6ZSBkb3duIHRvIGF2b2lkIGN1dG9mZg0KICAgICAgICAgICBjdXRvZmZzLmF0ID0gYygwLjcsMC41LDAuMywwLjEsMCkpICsNCiAjV2UgcmVtb3ZlZCBzb21lIG9mIHRoZSBjdXRvZmZzIHRvIGF2b2lkIHRoZSBtYXNodXAgbmVhciB0aGUgb3JpZ2luLg0KDQogICNDaGFuZ2VkIHRoZSB0aGVtZSB0byBhdm9pZCBjdXRvZmYgcGxvdCB2YWx1ZXMuDQogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTQpICsgDQogIGxhYnMoeCA9ICJGYWxzZSBQb3NpdGl2ZSBSYXRlIiwgDQogICAgICAgeSA9ICJUcnVlIFBvc2l0aXZlIFJhdGUiKSArDQogICAgICBnZ3RpdGxlKCJST0MgUGxvdDogVHJhaW5pbmcgYW5kIFRlc3QiKQ0KcHJpbnQocF9wbG90KSANCg0KDQpwX3RyYWluIDwtDQogIGdncGxvdChyZXN1bHRzX3RyYWluLA0KICAgICAgICAgYWVzKG0gPSBDbGFzczEsIGQgPSBtYWpvcl9naWZ0ZXIsIGNvbG9yID0gdHlwZSkpICsNCiAgZ2VvbV9yb2MobGFiZWxzaXplID0gMy41LA0KICAgICAgICAgICBjdXRvZmZzLmF0ID0gYygwLjcsMC41LDAuMywwLjEsMCkpICsNCiANCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNikgKyANCiAgbGFicyh4ID0gIkZhbHNlIFBvc2l0aXZlIFJhdGUiLCANCiAgICAgICB5ID0gIlRydWUgUG9zaXRpdmUgUmF0ZSIpICsNCiAgICAgIGdndGl0bGUoIlJPQyBQbG90OiBUcmFpbmluZyBhbmQgVGVzdCIpDQoNCnBfdGVzdCA8LQ0KICBnZ3Bsb3QocmVzdWx0c190ZXN0LA0KICAgICAgICAgYWVzKG0gPSBDbGFzczEsIGQgPSBtYWpvcl9naWZ0ZXIsIGNvbG9yID0gdHlwZSkpICsNCiAgZ2VvbV9yb2MobGFiZWxzaXplID0gMy41LA0KICAgICAgICAgICBjdXRvZmZzLmF0ID0gYygwLjcsMC41LDAuMywwLjEsMCkpICsNCiANCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNikgKyANCiAgbGFicyh4ID0gIkZhbHNlIFBvc2l0aXZlIFJhdGUiLCANCiAgICAgICB5ID0gIlRydWUgUG9zaXRpdmUgUmF0ZSIpICsNCiAgICAgIGdndGl0bGUoIlJPQyBQbG90OiBUcmFpbmluZyBhbmQgVGVzdCIpDQoNCiNDYWxjdWxhdGluZyBBVUMgb2YgYm90aA0KcHJpbnQoY2FsY19hdWMocF90cmFpbikkQVVDKQ0KcHJpbnQoY2FsY19hdWMocF90ZXN0KSRBVUMpDQoNCg0KDQoNCg0KDQoNCmBgYA0KDQpSSURHRQ0KDQpgYGB7cn0NCg0KbGlicmFyeSgnZ2xtbmV0JykNCmxpYnJhcnkoJ2dsbW5ldFV0aWxzJykNCg0KcmlkZ2VfZml0MSA8LSBjdi5nbG1uZXQoSEguTGlmZXRpbWUuR2l2aW5nIH4gc2V4X2ZjdCArIGRvbm9yc2VnX2ZjdCArIE5vX29mX0NoaWxkcmVuLA0KICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV90cmFpbiwNCiAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwKQ0KDQojQWxwaGEgMCBzZXRzIHRoZSBSaWRnZQ0KcHJpbnQocmlkZ2VfZml0MSkNCnByaW50KHJpZGdlX2ZpdDEkbGFtYmRhLm1pbikNCg0KcHJpbnQocmlkZ2VfZml0MSRsYW1iZGEuMXNlKQ0KDQoNCmBgYA0KDQpMQVNTTw0KDQpgYGB7cn0NCg0KI1VzaW5nIGN2LmdsbW5ldCBmcm9tIGNsYXNzDQpscyhkYXRhX3RyYWluKSANCmlzLmZhY3RvcihkYXRhX3RyYWluJG1ham9yX2dpZnRlcikNCg0KbGFzc29fZml0IDwtIGN2LmdsbW5ldChtYWpvcl9naWZ0ZXIgfiBDbGFzcy5ZZWFyICsgQWdlICsgZGVnMV9mY3QgKyBtYWoxX2ZjdCArIHNleF9mY3QgKyBUb3RhbC5HaXZpbmcuWWVhcnMsDQogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3RyYWluLA0KICAgICAgICAgICAgICAgICAgICAgICAjQWxwaGEgMSBmb3IgbGFzc28NCiAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAxKQ0KDQpwcmludChsYXNzb19maXQkbGFtYmRhLm1pbikNCiMNCnByaW50KGxhc3NvX2ZpdCRsYW1iZGEuMXNlKQ0KDQpgYGANCg0KDQoNCg0KYGBge3J9DQoNCiNjb2VmKGxhc3NvX21vZCkNCiNEZWZhdWx0IHNldHRpbmcgaXMgbGFtYmRhLjFzZQ0KDQojRnJvbSB0aGUgYm9vayAtIHNob3dpbmcgY29udmVyZ2VuY2Ugd2l0aCBsYW1iZGEgdmFsdWVzDQojcGxvdChsYXNzb19tb2QkZ2xtbmV0LmZpdCwgeHZhcj0ibGFtYmRhIikNCiNhYmxpbmUodj1sb2coYyhsYXNzb19tb2QkbGFtYmRhLm1pbiwgbGFzc29fbW9kJGxhbWJkYS4xc2UpKSwgbHR5PTIpDQoNCmBgYA0KDQpgYGB7cn0NCg0KI2VuZXRfbW9kIDwtIGN2YS5nbG1uZXQoZGVwZW5kZW50IH4gaW5keTEgKyBpbmR5MiwNCiMgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLA0KIyAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSBzZXEoMCwxLCBieSA9IDAuMSkpDQoNCiNwcmludChlbmV0X21vZCkNCiNwbG90KGVuZXRfbW9kKQ0KDQoNCmBgYA0KDQpFTEFTVElDTkVUDQoNCmBgYHtyIGVsYXN0aWNuZXR9DQoNCm1pbmxvc3NwbG90KGVuZXRfbW9kLCANCiAgICAgICAgICAgIGN2LnR5cGUgPSAibWluIikNCg0KZ2V0X2FscGhhIDwtIGZ1bmN0aW9uKGZpdCkgew0KICBhbHBoYSA8LSBmaXQkYWxwaGENCiAgZXJyb3IgPC0gc2FwcGx5KGZpdCRtb2RsaXN0LCANCiAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKG1vZCkge21pbihtb2QkY3ZtKX0pDQogIGFscGhhW3doaWNoLm1pbihlcnJvcildDQp9DQoNCmdldF9tb2RlbF9wYXJhbXMgPC0gZnVuY3Rpb24oZml0KSB7DQogIGFscGhhIDwtIGZpdCRhbHBoYQ0KICBsYW1iZGFNaW4gPC0gc2FwcGx5KGZpdCRtb2RsaXN0LCBgW1tgLCAibGFtYmRhLm1pbiIpDQogIGxhbWJkYVNFIDwtIHNhcHBseShmaXQkbW9kbGlzdCwgYFtbYCwgImxhbWJkYS4xc2UiKQ0KICBlcnJvciA8LSBzYXBwbHkoZml0JG1vZGxpc3QsIGZ1bmN0aW9uKG1vZCkge21pbihtb2QkY3ZtKX0pDQogIGJlc3QgPC0gd2hpY2gubWluKGVycm9yKQ0KICBkYXRhLmZyYW1lKGFscGhhID0gYWxwaGFbYmVzdF0sIGxhbWJkYU1pbiA9IGxhbWJkYU1pbltiZXN0XSwNCiAgICAgICAgICAgICBsYW1iZGFTRSA9IGxhbWJkYVNFW2Jlc3RdLCBlcm9yID0gZXJyb3JbYmVzdF0pDQp9DQoNCmJlc3RfYWxwaGEgPC0gZ2V0X2FscGhhKGVuZXRfbW9kKQ0KcHJpbnQoYmVzdF9hbHBoYSkNCmdldF9tb2RlbF9wYXJhbXMoZW5ldF9tb2QpDQoNCmJlc3RfbW9kIDwtIGVuZXRfbW9kJG1vZGxpc3RbW3doaWNoKGVuZXRfbW9kJGFscGhhID09IGJlc3RfYWxwaGEpXV0NCg0KcHJpbnQoYmVzdF9tb2QpDQoNCg0KYGBgDQoNClJpZGdlcyBwbG90IC0gY291bGQgYmUgdXNlZnVsIGZvciBwbG90dGluZyBkb25hdGlvbnMgdnMgZG9ub3Igc2VnbWVudA0KDQpgYGB7cn0NCg0KbGlicmFyeSgnZ2dyaWRnZXMnKQ0KDQpzdW1tYXJ5KGRhdGFfdHJhaW4kdmFyaWFibGUpDQoNCmdncGxvdChkYXRhX3RyYWluLCBhZXMoeCA9IEhILkxpZmV0aW1lLkdpdmluZywgeSA9IGRvbm9yc2VnX2ZjdCkpICsgZ2VvbV9kZW5zaXR5X3JpZGdlcyhyZWxfbWluX2hlaWdodCA9IDAuMDA1KSArIHhsaW0oYygwLCA0MDApKSArIA0KICAgICAgZ2d0aXRsZSgiSEggTGlmZXRpbWUgR2l2aW5nIGJ5IERvbm9yIFNlZ21lbnQiKQ0KDQpgYGANCg0KYGBge3J9DQoNCmxpYnJhcnkoJ2NvcnJwbG90JykNCg0KI3JlbW92aW5nIElEIHppcCBhbmQgbm9ubnVtZXJpYyANCmNvcnJwbG90X2RhdGEgPC0gZGF0YWNsZWFuWy1jKDE6NDcsNTU6NTYsNTg6MTMwKV0NCg0KI0NvbnZlcnQgZnJvbSBjaGFyYWN0ZXIgdG8gbnVtZXJpYyBkYXRhIHR5cGUNCmNvbnZlcnRfZmFjMm51bSA8LSBmdW5jdGlvbih4KXsNCiAgYXMubnVtZXJpYyhhcy5mYWN0b3IoeCkpDQp9DQoNCmNvcnJwbG90X2RhdGEgPC0gbXV0YXRlX2F0KGNvcnJwbG90X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAudmFycyA9IGMoMTo4KSwNCiAgICAgICAgICAgICAgICAgICAgIC5mdW5zID0gY29udmVydF9mYWMybnVtKQ0KI21ha2luZyBhIG1hdHJpeA0KY2RfY29yIDwtIGNvcihjb3JycGxvdF9kYXRhKQ0KDQojY3JlYXRpbmcgY29ycmVsYXRpb24NCmNvbCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNCQjQ0MDAiLCAiI0VFOTk5MCIsIA0KICAiI0ZGRkZGRiIsICIjNzdBQUVFIiwgIiM0NDc3QkIiKSkNCmNvcnJwbG90KGNkX2NvciwgbWV0aG9kPSJjb2xvciIsIGNvbD1jb2woMTAwKSwNCiAgdHlwZT0ibG93ZXIiLCBhZGRDb2VmLmNvbCA9ICJibGFjayIsDQogIHRsLnBvcz0ibHQiLCB0bC5jb2w9ImJsYWNrIiwgDQogIHRsLmNleD0wLjcsIHRsLnNydD00NSwgDQogIG51bWJlci5jZXg9MC43LA0KICBkaWFnPUZBTFNFKQ0KDQpgYGANCg0KDQpSYW5kb20gRm9yZXN0DQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KCdyYW5kb21Gb3Jlc3QnKQ0KDQpyZl9maXRfZG9ub3IgPC0gcmFuZG9tRm9yZXN0KGRlcGVuZGVudCB+IC4sIA0KICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV90cmFpbiwNCiAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IGNsYXNzaWZpY2F0aW9uLA0KICAgICAgICAgICAgICAgICAgICAgICBtdHJ5ID0gNywNCiAgICAgICAgICAgICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEucm91Z2hmaXgsDQogICAgICAgICAgICAgICAgICAgICAgIG50cmVlID0gMjAwLA0KICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRhbmNlPVRSVUUNCiAgICAgICAgICAgICAgICAgICAgICAgKQ0KDQpwcmludChyZl9maXRfZG9ub3IpDQoNCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNn0NCg0KdmFySW1wUGxvdChyZl9maXRfZG9ub3IsIHNvcnQgPSBUUlVFLCANCiAgICAgICAgICAgbi52YXIgPSA1LA0KICAgICAgICAgICB0eXBlID0gMiwgY2xhc3MgPSBOVUxMLCBzY2FsZSA9IFRSVUUsIA0KICAgICAgICAgICBtYWluID0gZGVwYXJzZShzdWJzdGl0dXRlKHJmX2ZpdF9kb25vcikpKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCg0KbGlicmFyeSgncmFuZG9tRm9yZXN0RXhwbGFpbmVyJykNCg0KcGxvdF9taW5fZGVwdGhfZGlzdHJpYnV0aW9uKA0KICByZl9maXRfZG9ub3IsDQogIGsgPSAxMCwNCiAgbWluX25vX29mX3RyZWVzID0gMCwNCiAgbWVhbl9zYW1wbGUgPSAidG9wX3RyZWVzIiwNCiAgbWVhbl9zY2FsZSA9IEZBTFNFLA0KICBtZWFuX3JvdW5kID0gMiwNCiAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgbWluaW1hbCBkZXB0aCBhbmQgaXRzIG1lYW4iDQopDQoNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCiNTcGxpdHRpbmcgQ2F0ZWdvcnkgb3V0IHRvIGNoZWNrIGlmIHRoZSBjYXRlZ29yeSBpcyB1c2VmdWwgZm9yIGFuYWx5c2lzDQpkYXRhX2NhdGVnb3J5X3NwbGl0X291dCA8LSBkYXRhY2xlYW4gJT4lDQogIG11dGF0ZShDYXRlZ29yeS5Db2RlcyA9IHRyaW0oc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKENhdGVnb3J5LkNvZGVzKSwgInwiLCBmaXhlZCA9IFRSVUUpKSkgJT4lDQogIHVubmVzdChDYXRlZ29yeS5Db2RlcykgJT4lIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBDYXRlZ29yeS5Db2Rlcyx2YWx1ZXNfZnJvbSA9Q2F0ZWdvcnkuQ29kZXMsIHZhbHVlc19mbiA9IGxlbmd0aCkNCg0KDQpgYGANCg==
=======
LS0tCnRpdGxlOiAiQlJPQ09ERSBTdW1tYXJ5IFN0YXRpc3RpY3MiCmF1dGhvcjogIkFhcm9uIFdpbGxpcywgQ2Fubm9uIEJyb29rZSwgSm9zaHVhIEhlbmRlcnNvbiwgUnlhbiBSYWRjbGlmZiIKc3VidGl0bGU6IEJVUzY5NiBGaW5hbCBQcm9qZWN0IHYxMgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCiMgUGxlYXNlIGxlYXZlIHRoaXMgY29kZSBjaHVuayBhcyBpcy4gSXQgbWFrZXMgc29tZSBzbGlnaHQgZm9ybWF0dGluZyBjaGFuZ2VzIHRvIGFsdGVyIHRoZSBvdXRwdXQgdG8gYmUgbW9yZSBhZXN0aGV0aWNhbGx5IHBsZWFzaW5nLiAKCmxpYnJhcnkoJ2tuaXRyJykKCgojIENoYW5nZSB0aGUgbnVtYmVyIGluIHNldCBzZWVkIHRvIHlvdXIgb3duIGZhdm9yaXRlIG51bWJlcgpzZXQuc2VlZCgxODE4KQpvcHRpb25zKHdpZHRoPTcwKQpvcHRpb25zKHNjaXBlbj05OSkKCgojIHRoaXMgc2V0cyB0ZXh0IG91dHB1dHRlZCBpbiBjb2RlIGNodW5rcyB0byBzbWFsbApvcHRzX2NodW5rJHNldCh0aWR5Lm9wdHM9bGlzdCh3aWR0aC53cmFwPTUwKSx0aWR5PVRSVUUsIHNpemUgPSAidnNtYWxsIikgIApvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKICAgICAgICAgICAgICAgIyAiY2FjaGluZyIgc3RvcmVzIG9iamVjdHMgaW4gY29kZSBjaHVua3MgYW5kIG9ubHkgcmV3cml0ZXMgaWYgeW91IGNoYW5nZSB0aGluZ3MKICAgICAgICAgICAgICAgY2FjaGUgPSBUUlVFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIyBhdXRvbWF0aWNhbGx5IGRvd25sb2FkcyBkZXBlbmRlbmN5IGZpbGVzCiAgICAgICAgICAgICAgIGF1dG9kZXAgPSBUUlVFLAogICAgICAgICAgICAgICAjIAogICAgICAgICAgICAgICBjYWNoZS5jb21tZW50cyA9IEZBTFNFLAogICAgICAgICAgICAgICAjIAogICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsCiAgICAgICAgICAgICAgICMgY2hhbmdlIGZpZy53aWR0aCBhbmQgZmlnLmhlaWdodCB0byBjaGFuZ2UgdGhlIGNvZGUgaGVpZ2h0IGFuZCB3aWR0aCBieSBkZWZhdWx0CiAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDUuNSwgIAogICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gNC41LAogICAgICAgICAgICAgICBmaWcuYWxpZ249J2NlbnRlcicpCgoKYGBgCgpgYGB7ciBzZXR1cC0yfQoKIyBBbHdheXMgcHJpbnQgdGhpcyBvdXQgYmVmb3JlIHlvdXIgYXNzaWdubWVudApzZXNzaW9uSW5mbygpCmdldHdkKCkKCmBgYAoKCjwhLS0gIyMjIHN0YXJ0IGFuc3dlcmluZyB5b3VyIHByb2JsZW0gc2V0IGhlcmUgLS0+CjwhLS0gWW91IG1heSBleHBvcnQgeW91ciBob21ld29yayBpbiBlaXRoZXIgaHRtbCBvciBwZGYsIHdpdGggdGhlIGZvcm1lciB1c3VhbGx5IGJlaW5nIGVhc2llci4gCiAgICAgVG8gZXhwb3J0IG9yIGNvbXBpbGUgeW91ciBSbWQgZmlsZTogY2xpY2sgYWJvdmUgb24gJ0tuaXQnIHRoZW4gJ0tuaXQgdG8gSFRNTCcgLS0+CjwhLS0gQmUgc3VyZSB0byBzdWJtaXQgYm90aCB5b3VyIC5SbWQgZmlsZSBhbmQgdGhlIGNvbXBpbGVkIC5odG1sIG9yIC5wZGYgZmlsZSBmb3IgZnVsbCBjcmVkaXQgLS0+CgoKYGBge3Igc2V0dXAtM30KCiMgbG9hZCBhbGwgeW91ciBsaWJyYXJpZXMgaW4gdGhpcyBjaHVuayAKbGlicmFyeSgndGlkeXZlcnNlJykKbGlicmFyeSgiZnMiKQpsaWJyYXJ5KCdoZXJlJykKbGlicmFyeSgnZHBseXInKQpsaWJyYXJ5KCd0aWR5dmVyc2UnKQpsaWJyYXJ5KCdnZ3Bsb3QyJykKbGlicmFyeSgnZ2dyZXBlbCcpCmxpYnJhcnkoJ2dndGhlbWVzJykKbGlicmFyeSgnZm9yY2F0cycpCmxpYnJhcnkoJ3JzYW1wbGUnKQpsaWJyYXJ5KCdsdWJyaWRhdGUnKQpsaWJyYXJ5KCdnZ3RoZW1lcycpCmxpYnJhcnkoJ2thYmxlRXh0cmEnKQpsaWJyYXJ5KCdwYXN0ZWNzJykKbGlicmFyeSgndmlyaWRpcycpCmxpYnJhcnkoJ3Bsb3RseScpCmxpYnJhcnkoJ3RpZHlxdWFudCcpCmxpYnJhcnkoJ3NjYWxlcycpCgoKIyBub3RlLCBkbyBub3QgcnVuIGluc3RhbGwucGFja2FnZXMoKSBpbnNpZGUgYSBjb2RlIGNodW5rLiBpbnN0YWxsIHRoZW0gaW4gdGhlIGNvbnNvbGUgb3V0c2lkZSBvZiBhIGNvZGUgY2h1bmsuIAoKYGBgCgoKCiMjIFBhcnQgMSAtIEZpbmFsIFByb2plY3QgQ2xlYW5pbmcgYW5kIFN1bW1hcnkgU3RhdGlzdGljcyAKCjFhKSBMb2FkaW5nIGRhdGEKCmBgYHtyfQoKI1JlYWRpbmcgdGhlIGRhdGEgaW4gYW5kIGRvaW5nIG1pbm9yIGluaXRpYWwgY2xlYW5pbmcgaW4gdGhlIGZ1bmN0aW9uIGNhbGwKI1JlcHJvZHVjaWJsZSBkYXRhIGFuYWx5c2lzIHNob3VsZCBhdm9pZCBhbGwgYXV0b21hdGljIHN0cmluZyB0byBmYWN0b3IgY29udmVyc2lvbnMuCiNzdHJpcC53aGl0ZSByZW1vdmVzIHdoaXRlIHNwYWNlIAojbmEuc3RyaW5ncyBpcyBhIHN1YnN0aXR1dGlvbiBzbyBhbGwgdGhhdCBoYXZlICIiIHdpbGwgPSBuYQpkYXRhIDwtIHJlYWQuY3N2KGhlcmU6OmhlcmUoImZpbmFsX3Byb2plY3QiLCAiZG9ub3JfZGF0YS5jc3YiKSwKICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc3RyaXAud2hpdGUgPSBUUlVFLAogICAgICAgICAgICAgICAgIG5hLnN0cmluZ3MgPSAiIikKCgoKYGBgCgoKMWIpIEZpeGluZyB0aGUgd29ua3kgRE9CICYgRGF0YSBjbGVhbnVwCgpgYGB7cn0KCiMoQmlydGhkYXRlIGFuZCBBZ2UsIElEIGFzIGEgbnVtYmVyKWFkZGluZyBET0IgKEFnZS9TcG91c2UgQWdlKSBpbiB5ZWFycyBjb2x1bW5zIGFuZCBhZGRpbmcgdHdvIGZpZWxkcyBmb3IgYXNzaWdubWVudCBhbmQgbnVtYmVyIG9mIGNoaWxkcmVuCmRhdGFjbGVhbiA8LSBkYXRhICU+JQogIG11dGF0ZShCaXJ0aGRhdGUgPSBpZmVsc2UoQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIEJpcnRoZGF0ZSkpICU+JQogIG11dGF0ZShCaXJ0aGRhdGUgPSBtZHkoQmlydGhkYXRlKSkgJT4lCiAgbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IEJpcnRoZGF0ZSwgZW5kPVN5cy5EYXRlKCkpL2R1cmF0aW9uKG49MSwgdW5pdD0ieWVhcnMiKSkpKSAlPiUKICBtdXRhdGUoU3BvdXNlLkJpcnRoZGF0ZSA9IGlmZWxzZShTcG91c2UuQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIFNwb3VzZS5CaXJ0aGRhdGUpKSAlPiUKICBtdXRhdGUoU3BvdXNlLkJpcnRoZGF0ZSA9IG1keShTcG91c2UuQmlydGhkYXRlKSkgJT4lCiAgbXV0YXRlKFNwb3VzZS5BZ2UgPSBhcy5udW1lcmljKGZsb29yKGludGVydmFsKHN0YXJ0PSBTcG91c2UuQmlydGhkYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpICU+JQogIG11dGF0ZShJRCA9IGFzLm51bWVyaWMoSUQpKSAlPiUgCiAgbXV0YXRlKEFzc2lnbm1lbnRfZmxhZyA9IGlmZWxzZShpcy5uYShBc3NpZ25tZW50Lk51bWJlciksIDAsMSkpICU+JSAKICBtdXRhdGUoIE5vX29mX0NoaWxkcmVuID0gaWZlbHNlKGlzLm5hKENoaWxkLjEuSUQpLDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoaXMubmEoQ2hpbGQuMi5JRCksMSwyKSkpCgojY29uZmVycmFsIGRhdGVzCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjEgPSBpZmVsc2UoQ29uZmVycmFsLkRhdGUuMSA9PSAiMDAwMS0wMS0wMSIsIE5BLCBDb25mZXJyYWwuRGF0ZS4xKSkgJT4lCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjEgPSBtZHkoQ29uZmVycmFsLkRhdGUuMSkpICU+JQogIG11dGF0ZShDb25mZXJyYWwuRGF0ZS4xLkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IENvbmZlcnJhbC5EYXRlLjEsIGVuZD1TeXMuRGF0ZSgpKS9kdXJhdGlvbihuPTEsIHVuaXQ9InllYXJzIikpKSkgJT4lCiAgCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjIgPSBpZmVsc2UoQ29uZmVycmFsLkRhdGUuMiA9PSAiMDAwMS0wMS0wMSIsIE5BLCBDb25mZXJyYWwuRGF0ZS4yKSkgJT4lCiAgbXV0YXRlKENvbmZlcnJhbC5EYXRlLjIgPSBtZHkoQ29uZmVycmFsLkRhdGUuMikpICU+JQogIG11dGF0ZShDb25mZXJyYWwuRGF0ZS4yLkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IENvbmZlcnJhbC5EYXRlLjIsIGVuZD1TeXMuRGF0ZSgpKS9kdXJhdGlvbihuPTEsIHVuaXQ9InllYXJzIikpKSkgJT4lCiAgCiAgbXV0YXRlKExhc3QuQ29udGFjdC5CeS5BbnlvbmUgPSBpZmVsc2UoTGFzdC5Db250YWN0LkJ5LkFueW9uZSA9PSAiMDAwMS0wMS0wMSIsIE5BLCBMYXN0LkNvbnRhY3QuQnkuQW55b25lKSkgJT4lCiAgbXV0YXRlKExhc3QuQ29udGFjdC5CeS5BbnlvbmUgPSBtZHkoTGFzdC5Db250YWN0LkJ5LkFueW9uZSkpICU+JQogIG11dGF0ZShMYXN0LkNvbnRhY3QuQWdlID0gYXMubnVtZXJpYyhmbG9vcihpbnRlcnZhbChzdGFydD0gTGFzdC5Db250YWN0LkJ5LkFueW9uZSwgZW5kPVN5cy5EYXRlKCkpL2R1cmF0aW9uKG49MSwgdW5pdD0ieWVhcnMiKSkpKSAlPiUKICAKIG11dGF0ZShISC5GaXJzdC5HaWZ0LkRhdGUgPSBpZmVsc2UoSEguRmlyc3QuR2lmdC5EYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIEhILkZpcnN0LkdpZnQuRGF0ZSkpICU+JQogIG11dGF0ZShISC5GaXJzdC5HaWZ0LkRhdGUgPSBtZHkoSEguRmlyc3QuR2lmdC5EYXRlKSkgJT4lCm11dGF0ZShISC5GaXJzdC5HaWZ0LkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IEhILkZpcnN0LkdpZnQuRGF0ZSwgZW5kPVN5cy5EYXRlKCkpL2R1cmF0aW9uKG49MSwgdW5pdD0ieWVhcnMiKSkpKQoKI21ham9yIGdpZnQgCmRhdGFjbGVhbiA8LSAKICBkYXRhY2xlYW4gJT4lIAogIG11dGF0ZShtYWpvcl9naWZ0ZXIgPSBpZmVsc2UoTGlmZXRpbWUuR2l2aW5nID4gNTAwMDAsIDEsMCkgJT4lIGZhY3RvciguLCBsZXZlbHMgPSBjKCIwIiwiMSIpKSkKCgojc3BsaXR0aW5nIHVwIHRoZSBhZ2UgaW50byByYW5nZXMgYW5kIGNyZWF0aW5nIGNhdGVnb3J5IGZvciBlYXN5IHZpc3VhbGl6YXRpb24gCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgbXV0YXRlKGFnZV9yYW5nZSA9IAogICAgaWZlbHNlKEFnZSAlaW4lIDEwOjE5LCAiMTAgPCAyMCB5ZWFycyBvbGQiLAogICAgaWZlbHNlKEFnZSAlaW4lIDIwOjI5LCAiMjAgPCAzMCB5ZWFycyBvbGQiLCAKICAgIGlmZWxzZShBZ2UgJWluJSAzMDozOSwgIjMwIDwgNDAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA0MDo0OSwgIjQwIDwgNTAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA1MDo1OSwgIjUwIDwgNjAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA2MDo2OSwgIjYwIDwgNzAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA3MDo3OSwgIjcwIDwgODAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA4MDo4OSwgIjgwIDwgOTAgeWVhcnMgb2xkIiwKICAgIGlmZWxzZShBZ2UgJWluJSA5MDoxMjAsICI5MCsgeWVhcnMgb2xkIiwKICAgIE5BKSkpKSkpKSkpKQoKCiNzZWVpbmcgd2hhdCB3ZSBoYXZlCnRhYmxlKGRhdGFjbGVhbiRhZ2VfcmFuZ2UpCiM1MC02MCBpcyB0aGUgbW9zdCBjb21tb24gYWdlIHJhbmdlIAoKI2NyZWF0aW5nIGEgcmVnaW9uIGNvbHVtbiB1c2luZyB0aGUgY291bnR5IGRhdGEgYW5kIHRoZSBPTUIgTVNBIChNZXRyb3BvbGl0YW4gU3RhdGlzdGljYWwgQXJlYSkgZGVmaW5pdGlvbnMKCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgbXV0YXRlKHJlZ2lvbiA9IAogICAgaWZlbHNlKENvdW50eSA9PSAiU2FuIEx1aXMgT2Jpc3BvIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLAogICAgaWZlbHNlKENvdW50eSA9PSAiS2VybiIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBCZXJuYXJkaW5vIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLAogICAgaWZlbHNlKENvdW50eSA9PSAiU2FudGEgQmFyYmFyYSIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlZlbnR1cmEiICYgU3RhdGUgPT0gIkNBIiwgIlNvIENhbCIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJMb3MgQW5nZWxlcyIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIk9yYW5nZSIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlJpdmVyc2lkZSIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBEaWVnbyIgJiBTdGF0ZSA9PSAiQ0EiLCAiU28gQ2FsIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkltcGVyaWFsIiAmIFN0YXRlID09ICJDQSIsICJTbyBDYWwiLAogICAgaWZlbHNlKENvdW50eSA9PSAiS2luZyIgJiBTdGF0ZSA9PSAiV0EiLCAiU2VhdHRsZSIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJTbm9ob21pc2giICYgU3RhdGUgPT0gIldBIiwgIlNlYXR0bGUiLAogICAgaWZlbHNlKENvdW50eSA9PSAiUGllcmNlIiAmIFN0YXRlID09ICJXQSIsICJTZWF0dGxlIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkNsYWNrYW1hcyIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLAogICAgaWZlbHNlKENvdW50eSA9PSAiQ29sdW1iaWEiICYgU3RhdGUgPT0gIk9SIiwgIlBvcnRsYW5kIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIk11bHRub21haCIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLAogICAgaWZlbHNlKENvdW50eSA9PSAiV2FzaGluZ3RvbiIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLAogICAgaWZlbHNlKENvdW50eSA9PSAiWWFtaGlsbCIgJiBTdGF0ZSA9PSAiT1IiLCAiUG9ydGxhbmQiLAogICAgaWZlbHNlKENvdW50eSA9PSAiQ2xhcmsiICYgU3RhdGUgPT0gIldBIiwgIlBvcnRsYW5kIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNrYW1hbmlhIiAmIFN0YXRlID09ICJXQSIsICJQb3J0bGFuZCIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJEZW52ZXIiICYgU3RhdGUgPT0gIkNPIiwgIkRlbnZlciIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJBcmFwYWhvZSIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkplZmZlcnNvbiIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkFkYW1zIiAmIFN0YXRlID09ICJDTyIsICJEZW52ZXIiLAogICAgaWZlbHNlKENvdW50eSA9PSAiRG91Z2xhcyIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkJyb29tZmllbGQiICYgU3RhdGUgPT0gIkNPIiwgIkRlbnZlciIsICAgIAogICAgaWZlbHNlKENvdW50eSA9PSAiRWxiZXJ0IiAmIFN0YXRlID09ICJDTyIsICJEZW52ZXIiLAogICAgaWZlbHNlKENvdW50eSA9PSAiUGFyayIgJiBTdGF0ZSA9PSAiQ08iLCAiRGVudmVyIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkNsZWFyIENyZWVrIiAmIFN0YXRlID09ICJDTyIsICJEZW52ZXIiLAogICAgaWZlbHNlKENvdW50eSA9PSAiQWxhbWVkYSIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLAogICAgaWZlbHNlKENvdW50eSA9PSAiQ29udHJhIENvc3RhIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJNYXJpbiIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLAogICAgaWZlbHNlKENvdW50eSA9PSAiTW9udGVyZXkiICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIk5hcGEiICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBCZW5pdG8iICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBGcmFuY2lzY28iICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbiBNYXRlbyIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLAogICAgaWZlbHNlKENvdW50eSA9PSAiU2FudGEgQ2xhcmEiICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNhbnRhIENydXoiICYgU3RhdGUgPT0gIkNBIiwgIkJheSBBcmVhIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlNvbGFubyIgJiBTdGF0ZSA9PSAiQ0EiLCAiQmF5IEFyZWEiLAogICAgaWZlbHNlKENvdW50eSA9PSAiU29ub21hIiAmIFN0YXRlID09ICJDQSIsICJCYXkgQXJlYSIsCiAgICAgICAgICAgTkEpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkKCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgbXV0YXRlKHJlZ2lvbiA9IAogICAgaWZlbHNlKENvdW50eSA9PSAiS2luZ3MiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlF1ZWVucyIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiTmV3IFlvcmsiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkJyb254IiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJSaWNobW9uZCIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiV2VzdGNoZXN0ZXIiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIkJlcmdlbiIgJiBTdGF0ZSA9PSAiTlkiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiSHVkc29uIiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJQYXNzYWljIiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJQdXRuYW0iICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlJvY2tsYW5kIiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJTdWZmb2xrIiAmIFN0YXRlID09ICJOWSIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJOYXNzYXUiICYgU3RhdGUgPT0gIk5ZIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIk1pZGRsZXNleCIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiTW9ubW91dGgiICYgU3RhdGUgPT0gIk5KIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIk9jZWFuIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJTb21lcnNldCIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiRXNzZXgiICYgU3RhdGUgPT0gIk5KIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlVuaW9uIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJNb3JyaXMiICYgU3RhdGUgPT0gIk5KIiwgIk5ldyBZb3JrIiwKICAgIGlmZWxzZShDb3VudHkgPT0gIlN1c3NleCIgJiBTdGF0ZSA9PSAiTkoiLCAiTmV3IFlvcmsiLAogICAgaWZlbHNlKENvdW50eSA9PSAiSHVudGVyZG9uIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsCiAgICBpZmVsc2UoQ291bnR5ID09ICJQaWtlIiAmIFN0YXRlID09ICJOSiIsICJOZXcgWW9yayIsCiAgICByZWdpb24pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkKCgojIGNvZGUgbm9yIGNhbCByZWdpb24gYXMgYWxsIG90aGVycyBpbiBDQSBub3QgYWxyZWFkeSBkZWZpbmVkCgpkYXRhY2xlYW4gPC0gZGF0YWNsZWFuICU+JQogIG11dGF0ZShyZWdpb24gPSAKICAgIGlmZWxzZShTdGF0ZSA9PSAiQ0EiICYgaXMubmEocmVnaW9uKSA9PSBUUlVFLCAiTm9yIENhbCIsIHJlZ2lvbikpCgoKI1JlbW92aW5nIENvbHVtbnMgdGhhdCBwcm92aWRlIG5vIGJlbmVmaXQgCgpkYXRhY2xlYW4gPC0gc3Vic2V0KGRhdGFjbGVhbixzZWxlY3QgPSAtYyhBc3NpZ25tZW50Lk51bWJlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuaGFzLkhpc3RvcmljYWwuTW5ncgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFN1ZmZpeAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuRGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuTWFuYWdlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuUm9sZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuVGl0bGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50LlN0YXR1cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFN0cmF0ZWd5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsUHJvZ3Jlc3MuTGV2ZWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50Lkdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsQXNzaWdubWVudC5DYXRlZ29yeQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEZ1bmRpbmcuTWV0aG9kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEV4cGVjdGVkLkJvb2suRGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxRdWFsaWZpY2F0aW9uLkFtb3VudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxFeHBlY3RlZC5Cb29rLkFtb3VudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxFeHBlY3RlZC5Cb29rLkRhdGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsSGFyZC5HaWZ0LlRvdGFsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFNvZnQuQ3JlZGl0LlRvdGFsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFRvdGFsLkFzc2lnbm1lbnQuR2lmdHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsTm8ub2YuUGxlZGdlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxQcm9wb3NhbC4uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFByb3Bvc2FsLk5vdGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEhILkxpZmUuU3BvdXNlLkNyZWRpdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxMYXN0LkNvbnRhY3QuQnkuTWFuYWdlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxYLi5vZi5Db250YWN0cy5CeS5NYW5hZ2VyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLERvbm9yU2VhcmNoLlJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLGlXYXZlLlJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFdlYWx0aEVuZ2luZS5SYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxQaGlsYW50aHJvcGljLkNvbW1pdG1lbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkKI2NsZWFuaW5nIHVwIHppcCBjb2RlcyByZW1vdmluZyAtNCBhZnRlciAKZGF0YWNsZWFuJFppcCA8LSBnc3ViKGRhdGFjbGVhbiRaaXAsIHBhdHRlcm49Ii0uKiIsIHJlcGxhY2VtZW50ID0gIiIpCgojYWRkaW5nIHppcCBjb2RlIGRhdGEgYW5kIGNvbHVtbiAKemlwIDwtIHJlYWQuY3N2KGhlcmU6OmhlcmUoImZpbmFsX3Byb2plY3QiLCAiU2FsYXJ5X1ppcGNvZGUuY3N2IiksCiAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHN0cmlwLndoaXRlID0gVFJVRSwKICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzID0gIiIpCgoKI2FkZGluZyB6aXAgc2FsYXJ5IGNvbHVtbgpkYXRhY2xlYW4gPC1kYXRhY2xlYW4gJT4lCiAgICBtdXRhdGUoemlwY29kZV9zbHJ5ID0gVkxPT0tVUChaaXAsIHppcCwgTkFNRSwgUzE5MDJfQzAzXzAwMkUpKQoKI3NscnkgcmFuZ2UgCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgbXV0YXRlKHppcHNscnlfcmFuZ2UgPSAKICAgIGlmZWxzZSh6aXBjb2RlX3NscnkgJWluJSAxMDAwMDo4OTk5OSwgIjkwSy05OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDkwMDAwOjk5OTk5LCAiOTBLLTk5SyIsCiAgICBpZmVsc2UoemlwY29kZV9zbHJ5ICVpbiUgMTAwMDAwOjE0OTk5OSwgIjEwMEstMTQ5SyIsIAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDE1MDAwMDoxOTk5OTksICIxNTBLLTE5OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDIwMDAwMDoyNDk5OTksICIyMDBLLTI0OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDI1MDAwMDoyOTk5OTksICIyNTBLLTI5OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDMwMDAwMDozNDk5OTksICIzMDBLLTM0OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDM1MDAwMDozOTk5OTksICIzNTBLLTM5OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDQwMDAwMDo0OTk5OTksICI0MDBLLTQ5OUsiLAogICAgaWZlbHNlKHppcGNvZGVfc2xyeSAlaW4lIDUwMDAwMDo5OTk5OTksICI1MDBLLTk5OUsiLAogICAgTkEpKSkpKSkpKSkpKQoKc3VtKGlzLm5hKGRhdGFjbGVhbiR6aXBjb2RlX3NscnkpKQoKI2FkZGluZyBzY2hvbGFyc2hpcCBkYXRhICh5L24pCnNjaGxyIDwtIHJlYWQuY3N2KGhlcmU6OmhlcmUoImZpbmFsX3Byb2plY3QiLCAic2Nob2xhcnNoaXAuY3N2IiksCiAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHN0cmlwLndoaXRlID0gVFJVRSwKICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzID0gIiIpCgojYWRkaW5nIHNjaG9sYXJzaGlwIGNvbHVtbgpkYXRhY2xlYW4gPC1kYXRhY2xlYW4gJT4lCiAgICBtdXRhdGUoc2Nob2xhcnNoaXAgPSBWTE9PS1VQKElELCBzY2hsciwgSUQsIFNDSE9MQVJTSElQKSkgCgojcmVwbGFjaW5nIE5BIHdpdGggMCAKIGRhdGFjbGVhbiRzY2hvbGFyc2hpcCA8LSByZXBsYWNlX25hKGRhdGFjbGVhbiRzY2hvbGFyc2hpcCwnMCcpCiAKI3JlcGxhY2luZyBZIHdpdGggMSAKZGF0YWNsZWFuJHNjaG9sYXJzaGlwPC1pZmVsc2UoZGF0YWNsZWFuJHNjaG9sYXJzaGlwPT0iWSIsMSwwKQoKI2NoZWNraW5nIGhvdyBtYW55IGFyZSBOCnRhYmxlKGRhdGFjbGVhbiRzY2hvbGFyc2hpcCkKCgojY2hlY2tpbmcgYW5kIGRlbGV0aW5nIHNjaG9sYXJzaGlwIGNvbHVtbiAKY2xhc3MoZGF0YWNsZWFuJHNjaGxyX2ZjdCkKZGF0YWNsZWFuID0gc3Vic2V0KGRhdGFjbGVhbiwgc2VsZWN0ID0gLWMoc2Nob2xhcnNoaXApKQogIAojY2hlY2tpbmcgZm9yIGR1cGxpY2F0ZXMgTiA+MSBpbmRpY2F0ZXMgYSByZWNvcmRzIHZhbHVlcyBhcmUgaW4gdGhlIGZpbGUgdHdpY2UgCmRhdGFjbGVhbiAlPiUgZ3JvdXBfYnkoSUQpICU+JSBjb3VudCgpICU+JSBhcnJhbmdlKGRlc2MobikpCgojcmVtb3ZpbmcgZHVwbGljYXRlZCByZWNvcmRzCgpkYXRhY2xlYW4gPC0gdW5pcXVlKGRhdGFjbGVhbikKCiNuID0gMSBubyBJRCB3aXRoIG11bHRpcGxlIHJlY29yZHMgY2xlYW5lZCBvZiBkdXBlcwpkYXRhY2xlYW4gJT4lIGdyb3VwX2J5KElEKSAlPiUgY291bnQoKSAlPiUgYXJyYW5nZShkZXNjKG4pKQoKYGBgCgoKMWQgQ3JlYXRpbmcgbWFueSBtYW55IGZhY3RvciB2YXJpYWJsZXMKCmBgYHtyfQoKZGF0YWNsZWFuIDwtIAogIGRhdGFjbGVhbiAlPiUgCiAgI1NFWAogIG11dGF0ZShzZXhfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKFNleCksCnNleF9zaW1wbGUgPSAKICAgIGZjdF9sdW1wX24oU2V4LCBuID0gNCksCiNNQVJSSUVECm1hcnJpZWRfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKE1hcnJpZWQpLAogICNET05PUiBTRUdNRU5UCiAgZG9ub3JzZWdfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKERvbm9yLlNlZ21lbnQpLAogICAgICAgICBkb25vcnNlZ19zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKERvbm9yLlNlZ21lbnQsIG4gPSA0KSwKICAjQ09OVEFDVCBSVUxFCiAgICAgICAgIGNvbnRhY3RfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENvbnRhY3QuUnVsZXMpLAogICAgICAgICBjb250YWN0X3NpbXBsZSA9IAogICAgICAgICAgIGZjdF9sdW1wX24oQ29udGFjdC5SdWxlcywgbiA9IDQpLAogICNTUE9VU0UgTUFJTAogICAgICAgICBzcG9tYWlsX2ZjdCA9IAogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShTcG91c2UuTWFpbC5SdWxlcyksCiAgICAgICAgIHNwb21haWxfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihTcG91c2UuTWFpbC5SdWxlcywgbiA9IDQpLAogICNKT0IgVElUTEUKICAgICAgICAgam9idGl0bGVfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKEpvYi5UaXRsZSksCiAgICAgICAgIGpvYnRpdGxlX3NpbXBsZSA9IAogICAgICAgICAgIGZjdF9sdW1wX24oSm9iLlRpdGxlLCBuID0gNSksCiAgI0RFR1JFRSBUWVBFIDEKICAgICAgICAgZGVnMV9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoRGVncmVlLlR5cGUuMSksCiAgICAgICAgIGRlZzFfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihEZWdyZWUuVHlwZS4xLCBuID0gNSksCiAgI0RFR1JFRSBUWVBFIDIKICAgICAgICAgZGVnMl9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoRGVncmVlLlR5cGUuMiksCiAgICAgICAgIGRlZzJfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihEZWdyZWUuVHlwZS4yLCBuID0gNSksCiAgI01BSk9SIDEKICAgICAgICAgbWFqMV9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWFqb3IuMSksCiAgICAgICAgIG1hajFfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihNYWpvci4xLCBuID0gNSksCiAgI01BSk9SIDIKICAgICAgICAgbWFqMl9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWFqb3IuMiksCiAgICAgICAgIG1hajJfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihNYWpvci4yLCBuID0gNSksCiAgI01JTk9SIDEKICAgICAgICAgbWluMV9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWlub3IuMSksCiAgICAgICAgIG1pbjFfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihNaW5vci4xLCBuID0gNSksCiAgI01JTk9SIDIKICAgICAgICAgbWluMl9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoTWlub3IuMiksCiAgICAgICAgIG1pbjJfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihNaW5vci4yLCBuID0gNSksCiAgI1NDSE9PTCAxCiAgICAgICAgIHNjaG9vbDFfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKFNjaG9vbC4xKSwKICAgICAgICAgc2Nob29sMV9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKFNjaG9vbC4xLCBuID0gNSksCiAgI1NDSE9PTCAyCiAgICAgICAgIHNjaG9vbDJfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKFNjaG9vbC4yKSwKICAgICAgICAgc2Nob29sMl9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKFNjaG9vbC4yLCBuID0gNSksCiAgI0lOU1RJVFVUSU9OIFRZUEUKICAgICAgICAgaW5zdHR5cGVfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKEluc3RpdHV0aW9uLlR5cGUpLAogICAgICAgICBpbnN0dHlwZV9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKEluc3RpdHV0aW9uLlR5cGUsIG4gPSA1KSwKICAjRVhUUkFDVVJSSUNVTEFSCiAgICAgICAgIGV4dHJhX2ZjdCA9IAogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShFeHRyYWN1cnJpY3VsYXIpLAogICAgICAgICBleHRyYV9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKEV4dHJhY3VycmljdWxhciwgbiA9IDUpLAogICNISCBGSVJTVCBHSUZUIEZVTkQKICAgICAgICAgaGhmaXJzdGdpZnRfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKEhILkZpcnN0LkdpZnQuRnVuZCksCiAgICAgICAgIGhoZmlyc3RnaWZ0X3NpbXBsZSA9IAogICAgICAgICAgIGZjdF9sdW1wX24oSEguRmlyc3QuR2lmdC5GdW5kLCBuID0gNSksCiNDSElMRCAxIEVOUk9MTCBTVEFUVVMKICAgICAgICAgY2gxX2Vucm9sbF9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMS5FbnJvbGwuU3RhdHVzKSwKICAgICAgICAgY2gxX2Vucm9sbF9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjEuRW5yb2xsLlN0YXR1cywgbiA9IDQpLAojQ0hJTEQgMSBNQUpPUgogICAgICAgICBjaDFfbWFqX2ZjdCA9IAogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShDaGlsZC4xLk1ham9yKSwKICAgICAgICAgY2gxX21hal9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjEuTWFqb3IsIG4gPSA0KSwKI0NISUxEIDEgTUlOT1IKICAgICAgICAgY2gxX21pbl9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMS5NaW5vciksCiAgICAgICAgIGNoMV9taW5fc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4xLk1pbm9yLCBuID0gNCksCiNDSElMRCAxIFNDSE9PTAogICAgICAgICBjaDFfc2Nob29sX2ZjdCA9IAogICAgICAgICAgIGZjdF9leHBsaWNpdF9uYShDaGlsZC4xLlNjaG9vbCksCiAgICAgICAgIGNoMV9zY2hvb2xfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4xLlNjaG9vbCwgbiA9IDQpLAojQ0hJTEQgMSBGRUVERVIKICAgICAgICAgY2gxX2ZlZWRlcl9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMS5GZWVkZXIuU2Nob29sKSwKICAgICAgICAgY2gxX2ZlZWRlcl9zaW1wbGUgPSAKICAgICAgICAgICBmY3RfbHVtcF9uKENoaWxkLjEuRmVlZGVyLlNjaG9vbCwgbiA9IDQpLAojQ0hJTEQgMiBFTlJPTEwgU1RBVFVTCiAgICAgICAgIGNoMV9lbnJvbGxfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjIuRW5yb2xsLlN0YXR1cyksCiAgICAgICAgIGNoMl9lbnJvbGxfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4yLkVucm9sbC5TdGF0dXMsIG4gPSA0KSwKI0NISUxEIDIgTUFKT1IKICAgICAgICAgY2gyX21hal9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMi5NYWpvciksCiAgICAgICAgIGNoMl9tYWpfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4yLk1ham9yLCBuID0gNCksCiNDSElMRCAyIE1JTk9SCiAgICAgICAgIGNoMl9taW5fZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjIuTWlub3IpLAogICAgICAgICBjaDJfbWluX3NpbXBsZSA9IAogICAgICAgICAgIGZjdF9sdW1wX24oQ2hpbGQuMi5NaW5vciwgbiA9IDQpLAojQ0hJTEQgMiBTQ0hPT0wKICAgICAgICAgY2gyX3NjaG9vbF9mY3QgPSAKICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoQ2hpbGQuMi5TY2hvb2wpLAogICAgICAgICBjaDJfc2Nob29sX3NpbXBsZSA9IAogICAgICAgICAgIGZjdF9sdW1wX24oQ2hpbGQuMi5TY2hvb2wsIG4gPSA0KSwKI0NISUxEIDIgRkVFREVSCiAgICAgICAgIGNoMl9mZWVkZXJfZmN0ID0gCiAgICAgICAgICAgZmN0X2V4cGxpY2l0X25hKENoaWxkLjIuRmVlZGVyLlNjaG9vbCksCiAgICAgICAgIGNoMl9mZWVkZXJfc2ltcGxlID0gCiAgICAgICAgICAgZmN0X2x1bXBfbihDaGlsZC4yLkZlZWRlci5TY2hvb2wsIG4gPSA0KSwKCiAgICApCgoKCiNjaGVja2luZyB0byBzZWUgaWYgaXRzIGEgZmFjdG9yCiNjbGFzcyhkYXRhY2xlYW4kc2V4X2ZjdCkKI2NsYXNzKGRhdGFjbGVhbiRkb25vcnNlZ19mY3QpCiNjbGFzcyhkYXRhY2xlYW4kY29udGFjdF9mY3QpCiNjbGFzcyhkYXRhY2xlYW4kc3BvbWFpbF9mY3QpCgojY2hlY2tpbmcgbGV2ZWxzCiNsZXZlbHMoZGF0YWNsZWFuJHNleF9zaW1wbGUpCiNsZXZlbHMoZGF0YWNsZWFuJGRvbm9yc2VnX3NpbXBsZSkKI2xldmVscyhkYXRhY2xlYW4kY29udGFjdF9zaW1wbGUpCiNsZXZlbHMoZGF0YWNsZWFuJHNwb21haWxfc2ltcGxlKQojbGV2ZWxzKGRhdGFjbGVhbiRoaGZpcnN0Z2lmdF9zaW1wbGUpCgojY3JlYXRpbmcgYSB0YWJsZSBhZ2FpbnN0IFNleCBjb2x1bW4gCiN0YWJsZShkYXRhY2xlYW4kc2V4X2ZjdCwgZGF0YWNsZWFuJHNleF9zaW1wbGUpCgoKYGBgCgoKCkRvbm9yU2VnbWVudCBBbmFseXNpcwoKYGBge3J9CiNncm91cGluZyBieSBkb25vcnNlZ21lbnQgYW5kIGFuYWx5emluZyAKZGF0YWNsZWFuICU+JQogIGdyb3VwX2J5KERvbm9yLlNlZ21lbnQpICU+JQogIHN1bW1hcmlzZShDb3VudCA9IGxlbmd0aChEb25vci5TZWdtZW50KSwKICAgICAgICAgICAgbWVhbl90b3RhbF9naXYgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZykpICU+JQogIGFycmFuZ2UoLUNvdW50KSAlPiUKICBmaWx0ZXIoQ291bnQgPj0gMTAwKSAlPiUKICAjYWRkZWQgc2NhbGVzIHBhY2thZ2UgdG8gaGF2ZSB0aGUgdmFsdWVzIHNob3cgaW4gZG9sbGFyIAogIG11dGF0ZShtZWFuX3RvdGFsX2dpdiA9IGRvbGxhcihtZWFuX3RvdGFsX2dpdikpICU+JQogIGthYmxlKGNvbC5uYW1lcyA9IGMoIkRvbm9yIFNlZ21lbnQiLCAiQ291bnQiLCAiTWVhbiBISCBMaWZldGltZSBHaXZpbmciKSwgYWxpZ249cmVwKCdjJywgMykpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikKICAKCmBgYAoKRmlyc3QgZ2lmdCBzaXplIApgYGB7cn0KYXEgPC0gcXVhbnRpbGUoZGF0YWNsZWFuJEhILkZpcnN0LkdpZnQuQW1vdW50LCBwcm9icyA9IGMoLjI1LC41MCwuNzUsLjksLjk5KSwgbmEucm0gPSBUUlVFKQoKYXEgPC0gYXMuZGF0YS5mcmFtZShhcSkKCmFxJGFxIDwtIGRvbGxhcihhcSRhcSkKCmFxICU+JQogIGthYmxlKGNvbC5uYW1lcyA9ICJRdWFudGlsZSIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikKICAKCmBgYApDb25zZWN1dGl2ZSBnaXZpbmcKYGBge3J9CiNjb25zZWN1dGl2ZSB5ZWFycyBvZiBnaXZpbmcgCmRhdGFjbGVhbiAlPiUKICBmaWx0ZXIoTWF4LkNvbnNlYy5GaXNjYWwuWWVhcnMgPiAwKSAlPiUKICBnZ3Bsb3QoYWVzKE1heC5Db25zZWMuRmlzY2FsLlllYXJzKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIiMwMDI4NDUiLCBiaW5zID0gMjApICsgCiAgdGhlbWVfZWNvbm9taXN0X3doaXRlKCkgKwogIGdndGl0bGUoIkNvbnNlY3V0aXZlIFllYXJzIG9mIEdpdmluZyBEaXN0cmlidXRpb24iKSArIAogIHhsYWIoTlVMTCkgKyB5bGFiKE5VTEwpICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEyMCwyKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAwMDAwMCw1MDAwKSkgCgoKCmBgYAoKTGlmZXRpbWUgZ2l2aW5nIGJhc2VkIG9uIG51bWJlciBvZiBjaGlsZHJlbiAKCmBgYHtyfQpkYXRhY2xlYW4gJT4lCiAgZmlsdGVyKEhILkxpZmV0aW1lLkdpdmluZyA8PSAxMDAwMCkgJT4lCiAgZmlsdGVyKEhILkxpZmV0aW1lLkdpdmluZyA+IDApICU+JQogIG11dGF0ZShgTm9fb2ZfQ2hpbGRyZW5gID0gYXMuZmFjdG9yKGBOb19vZl9DaGlsZHJlbmApKSAlPiUKICBnZ3Bsb3QoYWVzKEhILkxpZmV0aW1lLkdpdmluZywgZmlsbCA9IGBOb19vZl9DaGlsZHJlbmApKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCkgKyB0aGVtZV9lY29ub21pc3Rfd2hpdGUoKSArCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTAwMDAwLDEwMDApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwMDAwMDAwMCw1MDAwKSkgKwogIGdndGl0bGUoIkdpdmluZyBkaXN0cmlidXRpb24gYW5kIG51bWJlciBvZiBjaGlsZHJlbiIpKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzAwMjg0NSIsICIjMDBjZmNjIiwgIiNmZjk5NzMiKSkKCgoKYGBgCgoKTWVhbiwgTWVkaWFuLCBhbmQgQ291bnQgb2YgR2l2aW5nIGluIEFnZSBSYW5nZXMgCgpgYGB7cn0KCmFnZV9yYW5nZV9naXZpbmcgPC0gZGF0YWNsZWFuICU+JQogIGdyb3VwX2J5KGFnZV9yYW5nZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19naXZpbmcgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgbWVkX2dpdmluZyA9IG1lZGlhbihISC5MaWZldGltZS5HaXZpbmcsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIGFtb3VudF9vZl9wZW9wbGVfaW5fYWdlX3JhbmdlID0gbigpKQoKCmdsaW1wc2UoYWdlX3JhbmdlX2dpdmluZykKCmBgYAoKCgoKCiMjIFBhcnQgMgoKMmEpIFBsb3R0aW5nIGF2ZXJhZ2UgZ2l2aW5nIGJ5IGFnZSByYW5nZSAKCgpgYGB7cn0KCmFnZV9yYW5nZV9naXZpbmcgPC0KICBhZ2VfcmFuZ2VfZ2l2aW5nICU+JQogIG11dGF0ZShhZ2VfcmFuZ2UgPSBmYWN0b3IoYWdlX3JhbmdlKSkKCmdncGxvdChhZ2VfcmFuZ2VfZ2l2aW5nLCBhZXMoYWdlX3JhbmdlLCBhdmdfZ2l2aW5nKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0PTEpKQoKCmBgYAoKCjJiKSBDb3VudCBvZiBkb25vcnMgYmFzZWQgb24gYWdlIHJhbmdlIChhbm90aGVyIHdheSB0byBsb29rIGF0IGl0KQoKCmBgYHtyfQoKZ2dwbG90KGRhdGFjbGVhbiwgCiAgICAgICBhZXMoYWdlX3JhbmdlKSkgKyAKICAgICAgIGdlb21fYmFyKCkgKyAKICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3Q9MSkpICsgCiAgbGFicyh0aXRsZSA9ICJDb3VudCBvZiBBZ2UgUmFuZ2VzIiwgeCA9ICIiLCB5ID0gIiIpCiAgCgpgYGAKCjJjKSBCb3hwbG90IG9mIHRoZSBBZ2UgUmFuZ2VzIEFnYWluc3QgdGhlIExpZmV0aW1lIEdpdmluZyBBbW91bnRzIHdpdGggYSBsb2cgc2NhbGUgYXBwbGllZCAtIHRoZSByZWFzb24gd2UgYXBwbGllZCBsb2cgc2NhbGUgaXMgdG8gcmVzb2x2ZSBpc3N1ZXMgd2l0aCB2aXN1YWxpemF0aW9ucyB0aGF0IHNrZXcgdG93YXJkcyBsYXJnZSB2YWx1ZXMgaW4gb3VyIGRhdGFzZXQuIAoKCmBgYHtyfQoKZ2dwbG90KGRhdGFjbGVhbiwgYWVzKGFnZV9yYW5nZSxISC5MaWZldGltZS5HaXZpbmcsZmlsbCA9IGFnZV9yYW5nZSkpICsgCiAgZ2VvbV9ib3hwbG90KAogIG91dGxpZXIuY29sb3VyID0gInJlZCIpICsgCiAgc2NhbGVfeV9sb2cxMCgpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpCiAgCgpgYGAKCjJkKSBTcGxpdHRpbmcgYnkgYWdlIGFuZCBnZW5kZXIgCgoKYGBge3J9CgoKI2NyZWF0aW5nIGJveHBsb3RzIApkYXRhY2xlYW4gJT4lIAogIGZpbHRlcihBZ2UgPCAxMDApICU+JSAjcmVtb3ZpbmcgdGhlIHdlaXJkIG91dGxpZXJzIHRoYXQgYXJlIG92ZXIgMTAwIAogIGZpbHRlcihTZXggJWluJSBjKCJNIiwgIkYiKSkgJT4lCiAgZ2dwbG90KGFlcyhTZXgsIEFnZSkpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyAKICB0aGVtZV9lY29ub21pc3QoKSArIAogIGdndGl0bGUoIkFnZXMgb2YgRG9ub3JzIEJhc2VkIG9uIEdlbmRlciIpICsgCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkKICAKCmBgYApHaXZpbmcgYnkgZ2VuZGVyCgoKYGBge3J9CgojcmVtb3ZlIE5BcyBVIFggCnEgPC0gZ2dwbG90KGRhdGFjbGVhbikKcSArIHN0YXRfc3VtbWFyeV9iaW4oCiAgYWVzKHkgPSBISC5MaWZldGltZS5HaXZpbmcsIHggPSBzZXhfc2ltcGxlKSwgCiAgZnVuLnkgPSAibWVhbiIsIGdlb20gPSAiYmFyIikKCnN1bW1hcnkoZGF0YWNsZWFuJHNleF9zaW1wbGUpCgpgYGAKCk1lYW4gYWdlIGJ5IGdlbmRlcgoKCmBgYHtyfQojYnJlYWtkb3duIG9mIHNleHMgCnRhbGx5KGdyb3VwX2J5KGRhdGFjbGVhbiwgU2V4KSkKCnN1bW1hcml6ZShncm91cF9ieShkYXRhY2xlYW4sIFNleCksIAogICAgICAgICAgYXZnX2dpdmluZyA9IG1lYW4oSEguTGlmZXRpbWUuR2l2aW5nLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgYXZnX2FnZSA9IG1lYW4oQWdlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgbWVkX2FnZSA9IG1lZGlhbihBZ2UsIG5hLnJtID0gVFJVRSkpCgojZ3JvdXBpbmcgYnkgc2V4IGFuZCBhZ2UgcmFuZ2UgZm9yIHNsaWRlcyAKdGFsbHkoZ3JvdXBfYnkoZGF0YWNsZWFuLCBTZXgsIGFnZV9yYW5nZSkpCgoKCmBgYAoKCgoyZSkgRGlzdHJpYnV0aW9uIG9mIHBlb3BsZSBpbiB0aGUgc3RhdGVzIHRoYXQgdGhleSBsaXZlLgoKYGBge3J9CgogIGRhdGFjbGVhbiAlPiUKICBtdXRhdGUoU3RhdGUgPSBpZmVsc2UoU3RhdGUgPT0gIiAiLCAiTkEiLCBTdGF0ZSkpICU+JQogIGZpbHRlcihTdGF0ZSAhPSAiTkEiKSAlPiUKICBncm91cF9ieShTdGF0ZSkgJT4lCiAgc3VtbWFyaXNlKENvdW50ID0gbGVuZ3RoKFN0YXRlKSkgJT4lCiAgZmlsdGVyKENvdW50ID4gODAwKSAlPiUKICBhcnJhbmdlKC1Db3VudCkgJT4lCiAga2FibGUoY29sLm5hbWVzID0gYygiRG9ub3IncyBTdGF0ZSIsICJDb3VudCIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiksCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikKICAKIAogIAogIAoKCmBgYAoKMmYpIExvb2tpbmcgYXQgYWxsIGRvbm9ycyBmaXJzdCBnaWZ0IGFtb3VudC4gNzUlIG1hZGUgYSBmaXJzdCBnaWZ0IG9mIDwxMDAuIAoKYGBge3J9Cgogbm9fbm9uX2Rvbm9ycyA8LSBkYXRhY2xlYW4gJT4lCiAgZmlsdGVyKExpZmV0aW1lLkdpdmluZyAhPSAwKQogIApuZCA8LSBxdWFudGlsZShub19ub25fZG9ub3JzJEhILkZpcnN0LkdpZnQuQW1vdW50LCBwcm9icyA9IGMoLjI1LC41MCwuNzUsLjksLjk5KSwgbmEucm0gPSBUUlVFKQoKbmQgPC0gYXMuZGF0YS5mcmFtZShuZCkKCm5kICU+JQogIGthYmxlKGNvbC5uYW1lcyA9ICJRdWFudGlsZSIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikKICAKICAKCgpgYGAKCgoKIyMgTW9kZWxpbmcgZm9yIHlvdSAKClNwbGl0IGRhdGEKCmBgYCB7cn0KI2NvbnZlcnRpbmcgbWFycmllZCBZIGFuZCBOIHRvIDEgYW5kIDAgCmRhdGFjbGVhbiA8LSBkYXRhY2xlYW4gJT4lCiAgICAgIG11dGF0ZShNYXJyaWVkX3NpbXBsZSA9IGlmZWxzZShNYXJyaWVkID09ICJOIiwwLDEpKQoKZGF0YWNsZWFuIDwtIGRhdGFjbGVhbiAlPiUKICBtdXRhdGUoaGgubGlmZXRpbWUuZ2l2aW5nX2ZjdCA9IGFzLmZhY3RvcihISC5MaWZldGltZS5HaXZpbmcpKQoKCmxpYnJhcnkoInJzYW1wbGUiKQoKZGF0YV9zcGxpdCA8LSBpbml0aWFsX3NwbGl0KGRhdGFjbGVhbiwgcHJvcCA9IDAuNzUpCgpkYXRhX3RyYWluIDwtIHRyYWluaW5nKGRhdGFfc3BsaXQpCmRhdGFfdGVzdCA8LSB0ZXN0aW5nKGRhdGFfc3BsaXQpCgpgYGAKCgoKYGBge3J9CnAgPC0gZGF0YWNsZWFuICU+JQogIGdncGxvdChhZXMoQWdlKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTMwLCBmaWxsID0gImJsdWUiKSArIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsKICBnZ3RpdGxlKCJPdmVyYWxsIERvbm9yIEFnZSBEaXN0cmlidXRpb24iKSArIAogIHhsYWIoTlVMTCkgKyB5bGFiKE5VTEwpICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSg1LDEwMCxieSA9IDIwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMjAsMTAwLGJ5ID0gMjApKSArIHhsaW0oYygyMCwxMDApKQoKZ2dwbG90bHkocCkKICAKcAoKZ2dwbG90KGRhdGEgPSBkYXRhY2xlYW4sIGFlcyh4ID0gQWdlKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0iYmx1ZSIpKyB4bGltKGMoMjAsMTAwKSkKCiAgCgoKYGBgCgpBbm90aGVyIEhpc3RvZ3JhbQoKCmBgYHtyfQoKZGF0YWNsZWFuICU+JQogIGZpbHRlcihBZ2UgPj0gMTApICU+JQogIGZpbHRlcihBZ2UgPD0gOTApICU+JQogIGdncGxvdChhZXMoQWdlKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIiMwMDI4NDUiLCBiaW5zID0gMjApICsgdGhlbWVfZWNvbm9taXN0X3doaXRlKCkgKwogIGdndGl0bGUoIk92ZXJhbGwgRG9ub3IgQWdlIERpc3RyaWJ1dGlvbiIpICsgCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTIwLDUpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwMDAwMDAwLDIwMDApKSAKCmBgYApBZ2UgZGlzdHJpYnV0aW9uIGJ5IGdlbmRlciAKCmBgYHtyfQojQWdlIEdlbmRlciBmaWx0ZXJlZCBvdXQgYmVsb3cgMTUgYW5kIGFib3ZlIDkwIC0gYWxzbyByZW1vdmVkIFUgWCB0aGUgd2VpcmQgdmFsdWVzIApkYXRhY2xlYW4gJT4lCiAgZmlsdGVyKEFnZSA+PSAxNSkgJT4lCiAgZmlsdGVyKEFnZSA8PSA5MCkgJT4lCiAgbXV0YXRlKFNleCA9IGFzLmZhY3RvcihTZXgpKSAlPiUKICBmaWx0ZXIoU2V4ICE9ICJVIikgJT4lCiAgZmlsdGVyKFNleCAhPSAiWCIpICU+JQogIGdncGxvdChhZXMoQWdlLCBmaWxsID0gU2V4KSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjUpICsgdGhlbWVfZWNvbm9taXN0X3doaXRlKCkgKwogIGdndGl0bGUoIkFnZSBEaXN0cmlidXRpb24gYnkgR2VuZGVyIikgKyAKICB4bGFiKE5VTEwpICsgeWxhYihOVUxMKSArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMjAsMTApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDUwMDAwLDIwMDApKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjZmY5OTczIiwgIiMwMGNmY2MiKSkKYGBgCgpEb25vciBhZ2UgZGlzdHJpYnV0aW9uIGJ5IG1hcml0YWwgc3RhdHVzIAoKYGBge3J9CiNBZ2UgTWFyaXRhbCBTdGF0dXMKZGF0YWNsZWFuICU+JQogIGZpbHRlcihBZ2UgPj0gMjApICU+JQogIGZpbHRlcihBZ2UgPD0gODUpICU+JQogIGdncGxvdChhZXMoQWdlLCBmaWxsID0gTWFycmllZCkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDI1KSArIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsKICBnZ3RpdGxlKCJPdmVyYWxsIERvbm9yIEFnZSBEaXN0cmlidXRpb24gYnkgTWFyaXRhbCBTdGF0dXMiKSArIAogIHhsYWIoTlVMTCkgKyB5bGFiKE5VTEwpICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEyMCw1KSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw1MDAwMCwyMDAwKSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI2ZmOTk3MyIsICIjMDBjZmNjIikpCmBgYAoKTGluZWFyIE1vZGVsIAoKYGBge3J9CiNUaGVzZSB3aWxsIGZvY3VzIG9uIHByZWRpY3Rpbmcgd2hldGhlciBhIGNvbnN0aXR1ZW50IGlzIGEgZG9ub3Igb3Igbm9uLWRvbm9yLiAKCgoKbW9kMWxtIDwtIGxtKCBMaWZldGltZS5HaXZpbmcgfiBNYXJyaWVkX3NpbXBsZSwKICAgICAgICAgICBkYXRhID0gZGF0YWNsZWFuKQoKbW9kMmxtIDwtIGxtKCBUb3RhbC5HaXZpbmcuWWVhcnMgfiBMaWZldGltZS5HaXZpbmcsCiAgICAgICAgICAgZGF0YSA9IGRhdGFjbGVhbikKCnN1bW1hcnkobW9kMWxtKQpzdW1tYXJ5KG1vZDJsbSkKI2luY3JlYXNpbmcgdGhlIGdpdmluZyB5ZWFyIG9uZSB5ZWFyIGluY3JlYXNlIHRvdGFsIGdpdmluZyBieSAwLjAwMzUKCgpnZ3Bsb3QoZGF0YSA9IGRhdGFfdHJhaW4sIGFlcyh4ID0gQWdlLCB5ID0gbG9nKEhILkxpZmV0aW1lLkdpdmluZykpKSArIGdlb21fcG9pbnQoYWxwaGEgPSAxLzEwKSArIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKSArIGZhY2V0X3dyYXAofmRvbm9yc2VnX2ZjdCkgKyB0aGVtZV9jbGVhbihiYXNlX3NpemUgPSA4KSArIGxhYnMoeCA9ICJYIiwgeSA9ICJZIikgKwogICAgICBnZ3RpdGxlKCJUaXRsZSIpCgoKCmdncGxvdChkYXRhID0gZGF0YV90cmFpbiwgYWVzKHggPSBBZ2UsIHkgPSBsb2coSEguRmlyc3QuR2lmdC5BbW91bnQpKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMS8xMCkgKyBnZW9tX3Ntb290aChtZXRob2QgPSBsbSkgKyBmYWNldF93cmFwKH5kb25vcnNlZ19mY3QpICsgdGhlbWVfY2xlYW4oYmFzZV9zaXplID0gOCkgKyBsYWJzKHggPSAiWCIsIHkgPSAiWSIpICsKICAgICAgZ2d0aXRsZSgiVGl0bGUiKQoKI1RoaXMgcGxvdCBhY3R1YWxseSBoYXMgc29tZSBpbnRlcmVzdGluZyByZXN1bHRzCmdncGxvdChkYXRhID0gZGF0YV90cmFpbiwgYWVzKHggPSBBZ2UsIHkgPSBsb2coTGlmZXRpbWUuR2l2aW5nKSkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDEvMTApICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0pICsgZmFjZXRfd3JhcCh+Tm9fb2ZfQ2hpbGRyZW4pICsgdGhlbWVfY2xlYW4oYmFzZV9zaXplID0gOCkgKyBsYWJzKHggPSAiWCIsIHkgPSAiWSIpICsKICAgICAgZ2d0aXRsZSgiVGl0bGUiKQoKCmRhdGFfdHJhaW4gJT4lIAogIHNlbGVjdF9pZihpcy5mYWN0b3IpICU+JSAKICBnbGltcHNlKCkKCgpgYGAKCgoKTU9SRSBNT0RFTFMKCkJpZyBsb2dpc3RpYyBtb2RlbAoKYGBge3J9CgojIFNldCBmYW1pbHkgdG8gYmlub21pYWwgdG8gc2V0IGxvZ2lzdGljIGZ1bmN0aW9uCiMgUnVuIHRoZSBtb2RlbCBvbiB0aGUgdHJhaW5pbmcgc2V0Cgpkb25vcl9sb2dpdDEgPC0KICBnbG0oaGgubGlmZXRpbWUuZ2l2aW5nX2ZjdCB+IE1hcnJpZWRfc2ltcGxlLAogICAgICBmYW1pbHkgPSAiYmlub21pYWwiLAogICAgICBkYXRhID0gZGF0YV90cmFpbikKCnN1bW1hcnkoZG9ub3JfbG9naXQxKQoKCmRvbm9yX2xvZ2l0MiA8LQogIGdsbShoaC5saWZldGltZS5naXZpbmdfZmN0IH4gTm9fb2ZfQ2hpbGRyZW4sCiAgICAgIGZhbWlseSA9ICJiaW5vbWlhbCIsCiAgICAgIGRhdGEgPSBkYXRhX3RyYWluKQoKc3VtbWFyeShkb25vcl9sb2dpdDIpCgoKCgoKCgojc3VtbWFyeShkYXRhX3RyYWluJG1ham9yX2dpZnRlcikKCmRvbm9yX2xvZ2l0MyA8LQogIGdsbShtYWpvcl9naWZ0ZXIgfiBNYXJyaWVkX3NpbXBsZSArIE5vX29mX0NoaWxkcmVuICsgZG9ub3JzZWdfc2ltcGxlICsgQXNzaWdubWVudF9mbGFnICsgVG90YWwuR2l2aW5nLlllYXJzLAogICAgICBmYW1pbHkgPSAiYmlub21pYWwiLAogICAgICBkYXRhID0gZGF0YV90cmFpbikKCnN1bW1hcnkoZG9ub3JfbG9naXQzKQpleHAoZG9ub3JfbG9naXQzJGNvZWZmaWNpZW50cykKCiN0cmFpbmluZyBwcmVkaWN0aW9ucyBmb3IgaW4gc2FtcGxlIHByZWRzIApwcmVkc190cmFpbiA8LSBwcmVkaWN0KGRvbm9yX2xvZ2l0MywgbmV3ZGF0YSA9IGRhdGFfdHJhaW4sIHR5cGUgPSAicmVzcG9uc2UiKSAKCiN0ZXN0IHByZWRpY3RzIGZvciBPT1MgKG91dCBvZiBzYW1wbGUpCnByZWRzX3Rlc3QgPC0gcHJlZGljdChkb25vcl9sb2dpdDMsIG5ld2RhdGEgPSBkYXRhX3Rlc3QsIHR5cGUgPSAicmVzcG9uc2UiKQoKaGVhZChwcmVkc190cmFpbikKaGVhZChwcmVkc190ZXN0KQoKCgpyZXN1bHRzX3RyYWluIDwtIGRhdGEuZnJhbWUoCiAgYHRydXRoYCA9IGRhdGFfdHJhaW4gICAlPiUgc2VsZWN0KG1ham9yX2dpZnRlcikgJT4lIAogICAgbXV0YXRlKG1ham9yX2dpZnRlciA9IGFzLm51bWVyaWMobWFqb3JfZ2lmdGVyKSksCiAgYENsYXNzMWAgPSAgcHJlZHNfdHJhaW4sCiAgYHR5cGVgID0gcmVwKCJ0cmFpbiIsbGVuZ3RoKHByZWRzX3RyYWluKSkKKQoKcmVzdWx0c190ZXN0IDwtIGRhdGEuZnJhbWUoCiAgYHRydXRoYCA9IGRhdGFfdGVzdCAgICU+JSBzZWxlY3QobWFqb3JfZ2lmdGVyKSAlPiUgCiAgICBtdXRhdGUobWFqb3JfZ2lmdGVyID0gYXMubnVtZXJpYyhtYWpvcl9naWZ0ZXIpKSwKICBgQ2xhc3MxYCA9ICBwcmVkc190ZXN0LAogIGB0eXBlYCA9IHJlcCgidGVzdCIsbGVuZ3RoKHByZWRzX3Rlc3QpKQopCgpyZXN1bHRzIDwtIGJpbmRfcm93cyhyZXN1bHRzX3RyYWluLHJlc3VsdHNfdGVzdCkKCmRpbShyZXN1bHRzX3RyYWluKQpkaW0ocmVzdWx0c190ZXN0KQpkaW0ocmVzdWx0cykKCmxpYnJhcnkoJ3Bsb3RST0MnKQoKcF9wbG90IDwtCiAgZ2dwbG90KHJlc3VsdHMsCiAgICAgICAgIGFlcyhtID0gQ2xhc3MxLCBkID0gbWFqb3JfZ2lmdGVyLCBjb2xvciA9IHR5cGUpKSArCiAgZ2VvbV9yb2MobGFiZWxzaXplID0gMi41LAogICAgICAgICAgICNUb29rIHRoZSBsYWJlbHNpemUgZG93biB0byBhdm9pZCBjdXRvZmYKICAgICAgICAgICBjdXRvZmZzLmF0ID0gYygwLjcsMC41LDAuMywwLjEsMCkpICsKICNXZSByZW1vdmVkIHNvbWUgb2YgdGhlIGN1dG9mZnMgdG8gYXZvaWQgdGhlIG1hc2h1cCBuZWFyIHRoZSBvcmlnaW4uCgogICNDaGFuZ2VkIHRoZSB0aGVtZSB0byBhdm9pZCBjdXRvZmYgcGxvdCB2YWx1ZXMuCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNCkgKyAKICBsYWJzKHggPSAiRmFsc2UgUG9zaXRpdmUgUmF0ZSIsIAogICAgICAgeSA9ICJUcnVlIFBvc2l0aXZlIFJhdGUiKSArCiAgICAgIGdndGl0bGUoIlJPQyBQbG90OiBUcmFpbmluZyBhbmQgVGVzdCIpCnByaW50KHBfcGxvdCkgCgoKcF90cmFpbiA8LQogIGdncGxvdChyZXN1bHRzX3RyYWluLAogICAgICAgICBhZXMobSA9IENsYXNzMSwgZCA9IG1ham9yX2dpZnRlciwgY29sb3IgPSB0eXBlKSkgKwogIGdlb21fcm9jKGxhYmVsc2l6ZSA9IDMuNSwKICAgICAgICAgICBjdXRvZmZzLmF0ID0gYygwLjcsMC41LDAuMywwLjEsMCkpICsKIAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTYpICsgCiAgbGFicyh4ID0gIkZhbHNlIFBvc2l0aXZlIFJhdGUiLCAKICAgICAgIHkgPSAiVHJ1ZSBQb3NpdGl2ZSBSYXRlIikgKwogICAgICBnZ3RpdGxlKCJST0MgUGxvdDogVHJhaW5pbmcgYW5kIFRlc3QiKQoKcF90ZXN0IDwtCiAgZ2dwbG90KHJlc3VsdHNfdGVzdCwKICAgICAgICAgYWVzKG0gPSBDbGFzczEsIGQgPSBtYWpvcl9naWZ0ZXIsIGNvbG9yID0gdHlwZSkpICsKICBnZW9tX3JvYyhsYWJlbHNpemUgPSAzLjUsCiAgICAgICAgICAgY3V0b2Zmcy5hdCA9IGMoMC43LDAuNSwwLjMsMC4xLDApKSArCiAKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE2KSArIAogIGxhYnMoeCA9ICJGYWxzZSBQb3NpdGl2ZSBSYXRlIiwgCiAgICAgICB5ID0gIlRydWUgUG9zaXRpdmUgUmF0ZSIpICsKICAgICAgZ2d0aXRsZSgiUk9DIFBsb3Q6IFRyYWluaW5nIGFuZCBUZXN0IikKCiNDYWxjdWxhdGluZyBBVUMgb2YgYm90aApwcmludChjYWxjX2F1YyhwX3RyYWluKSRBVUMpCnByaW50KGNhbGNfYXVjKHBfdGVzdCkkQVVDKQoKCgoKCgoKYGBgCgpSSURHRQoKYGBge3J9CgpsaWJyYXJ5KCdnbG1uZXQnKQpsaWJyYXJ5KCdnbG1uZXRVdGlscycpCgpyaWRnZV9maXQxIDwtIGN2LmdsbW5ldChISC5MaWZldGltZS5HaXZpbmcgfiBzZXhfZmN0ICsgZG9ub3JzZWdfZmN0ICsgTm9fb2ZfQ2hpbGRyZW4sCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFfdHJhaW4sCiAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwKQoKI0FscGhhIDAgc2V0cyB0aGUgUmlkZ2UKcHJpbnQocmlkZ2VfZml0MSkKcHJpbnQocmlkZ2VfZml0MSRsYW1iZGEubWluKQoKcHJpbnQocmlkZ2VfZml0MSRsYW1iZGEuMXNlKQoKCmBgYAoKTEFTU08KCmBgYHtyfQoKI1VzaW5nIGN2LmdsbW5ldCBmcm9tIGNsYXNzCmxzKGRhdGFfdHJhaW4pIAppcy5mYWN0b3IoZGF0YV90cmFpbiRtYWpvcl9naWZ0ZXIpCmdsaW1wc2UoZGF0YV90cmFpbiRMaWZldGltZS5HaXZpbmcpCgpkYXRhX3RyYWluICU+JSAKICBzZWxlY3RfaWYoaXMuZmFjdG9yKSAlPiUgCiAgZ2xpbXBzZSgpCgoKbGlicmFyeShnbG1uZXQpCmxpYnJhcnkoZ2xtbmV0VXRpbHMpCmxhc3NvX2ZpdCA8LSBjdi5nbG1uZXQoTGlmZXRpbWUuR2l2aW5nIH4gam9idGl0bGVfc2ltcGxlICsgZGVnMV9zaW1wbGUgKyBzY2hvb2wxX3NpbXBsZSArIGhoZmlyc3RnaWZ0X3NpbXBsZSArIG1hajFfc2ltcGxlICsgZG9ub3JzZWdfc2ltcGxlLAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3RyYWluLAogICAgICAgICAgICAgICAgICAgICAgICNBbHBoYSAxIGZvciBsYXNzbwogICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMSkKCnByaW50KGxhc3NvX2ZpdCRsYW1iZGEubWluKQojCnByaW50KGxhc3NvX2ZpdCRsYW1iZGEuMXNlKQoKcGxvdChsYXNzb19maXQpCgpgYGAKCgoKCmBgYHtyfQoKY29lZihsYXNzb19maXQpCiNEZWZhdWx0IHNldHRpbmcgaXMgbGFtYmRhLjFzZQoKI0Zyb20gdGhlIGJvb2sgLSBzaG93aW5nIGNvbnZlcmdlbmNlIHdpdGggbGFtYmRhIHZhbHVlcwpwbG90KGxhc3NvX2ZpdCRnbG1uZXQuZml0LCB4dmFyPSJsYW1iZGEiKQphYmxpbmUodj1sb2coYyhsYXNzb19maXQkbGFtYmRhLm1pbiwgbGFzc29fZml0JGxhbWJkYS4xc2UpKSwgbHR5PTIpCgpgYGAKCmBgYHtyfQoKI2VuZXRfbW9kIDwtIGN2YS5nbG1uZXQoZGVwZW5kZW50IH4gaW5keTEgKyBpbmR5MiwKIyAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiMgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gc2VxKDAsMSwgYnkgPSAwLjEpKQoKI3ByaW50KGVuZXRfbW9kKQojcGxvdChlbmV0X21vZCkKCgpgYGAKCkVMQVNUSUNORVQKCmBgYHtyIGVsYXN0aWNuZXR9CgptaW5sb3NzcGxvdChlbmV0X21vZCwgCiAgICAgICAgICAgIGN2LnR5cGUgPSAibWluIikKCmdldF9hbHBoYSA8LSBmdW5jdGlvbihmaXQpIHsKICBhbHBoYSA8LSBmaXQkYWxwaGEKICBlcnJvciA8LSBzYXBwbHkoZml0JG1vZGxpc3QsIAogICAgICAgICAgICAgICAgICBmdW5jdGlvbihtb2QpIHttaW4obW9kJGN2bSl9KQogIGFscGhhW3doaWNoLm1pbihlcnJvcildCn0KCmdldF9tb2RlbF9wYXJhbXMgPC0gZnVuY3Rpb24oZml0KSB7CiAgYWxwaGEgPC0gZml0JGFscGhhCiAgbGFtYmRhTWluIDwtIHNhcHBseShmaXQkbW9kbGlzdCwgYFtbYCwgImxhbWJkYS5taW4iKQogIGxhbWJkYVNFIDwtIHNhcHBseShmaXQkbW9kbGlzdCwgYFtbYCwgImxhbWJkYS4xc2UiKQogIGVycm9yIDwtIHNhcHBseShmaXQkbW9kbGlzdCwgZnVuY3Rpb24obW9kKSB7bWluKG1vZCRjdm0pfSkKICBiZXN0IDwtIHdoaWNoLm1pbihlcnJvcikKICBkYXRhLmZyYW1lKGFscGhhID0gYWxwaGFbYmVzdF0sIGxhbWJkYU1pbiA9IGxhbWJkYU1pbltiZXN0XSwKICAgICAgICAgICAgIGxhbWJkYVNFID0gbGFtYmRhU0VbYmVzdF0sIGVyb3IgPSBlcnJvcltiZXN0XSkKfQoKYmVzdF9hbHBoYSA8LSBnZXRfYWxwaGEoZW5ldF9tb2QpCnByaW50KGJlc3RfYWxwaGEpCmdldF9tb2RlbF9wYXJhbXMoZW5ldF9tb2QpCgpiZXN0X21vZCA8LSBlbmV0X21vZCRtb2RsaXN0W1t3aGljaChlbmV0X21vZCRhbHBoYSA9PSBiZXN0X2FscGhhKV1dCgpwcmludChiZXN0X21vZCkKCgpgYGAKClJpZGdlcyBwbG90IC0gY291bGQgYmUgdXNlZnVsIGZvciBwbG90dGluZyBkb25hdGlvbnMgdnMgZG9ub3Igc2VnbWVudAoKYGBge3J9CgpsaWJyYXJ5KCdnZ3JpZGdlcycpCgpzdW1tYXJ5KGRhdGFfdHJhaW4kdmFyaWFibGUpCgpnZ3Bsb3QoZGF0YV90cmFpbiwgYWVzKHggPSBISC5MaWZldGltZS5HaXZpbmcsIHkgPSBkb25vcnNlZ19mY3QpKSArIGdlb21fZGVuc2l0eV9yaWRnZXMocmVsX21pbl9oZWlnaHQgPSAwLjAwNSkgKyB4bGltKGMoMCwgNDAwKSkgKyAKICAgICAgZ2d0aXRsZSgiSEggTGlmZXRpbWUgR2l2aW5nIGJ5IERvbm9yIFNlZ21lbnQiKQoKYGBgCgpgYGB7cn0KCmxpYnJhcnkoJ2NvcnJwbG90JykKCiNyZW1vdmluZyBJRCB6aXAgYW5kIG5vbm51bWVyaWMgCmNvcnJwbG90X2RhdGEgPC0gZGF0YWNsZWFuWy1jKDE6NDcsNTU6NTYsNTg6MTMwKV0KCiNDb252ZXJ0IGZyb20gY2hhcmFjdGVyIHRvIG51bWVyaWMgZGF0YSB0eXBlCmNvbnZlcnRfZmFjMm51bSA8LSBmdW5jdGlvbih4KXsKICBhcy5udW1lcmljKGFzLmZhY3Rvcih4KSkKfQoKY29ycnBsb3RfZGF0YSA8LSBtdXRhdGVfYXQoY29ycnBsb3RfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgLnZhcnMgPSBjKDE6OCksCiAgICAgICAgICAgICAgICAgICAgIC5mdW5zID0gY29udmVydF9mYWMybnVtKQojbWFraW5nIGEgbWF0cml4CmNkX2NvciA8LSBjb3IoY29ycnBsb3RfZGF0YSkKCiNjcmVhdGluZyBjb3JyZWxhdGlvbgpjb2wgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjQkI0NDAwIiwgIiNFRTk5OTAiLCAKICAiI0ZGRkZGRiIsICIjNzdBQUVFIiwgIiM0NDc3QkIiKSkKY29ycnBsb3QoY2RfY29yLCBtZXRob2Q9ImNvbG9yIiwgY29sPWNvbCgxMDApLAogIHR5cGU9Imxvd2VyIiwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLAogIHRsLnBvcz0ibHQiLCB0bC5jb2w9ImJsYWNrIiwgCiAgdGwuY2V4PTAuNywgdGwuc3J0PTQ1LCAKICBudW1iZXIuY2V4PTAuNywKICBkaWFnPUZBTFNFKQoKYGBgCgoKUmFuZG9tIEZvcmVzdAoKYGBge3J9CgpsaWJyYXJ5KCdyYW5kb21Gb3Jlc3QnKQoKcmZfZml0X2Rvbm9yIDwtIHJhbmRvbUZvcmVzdChkZXBlbmRlbnQgfiAuLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV90cmFpbiwKICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gY2xhc3NpZmljYXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgbXRyeSA9IDcsCiAgICAgICAgICAgICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEucm91Z2hmaXgsCiAgICAgICAgICAgICAgICAgICAgICAgbnRyZWUgPSAyMDAsCiAgICAgICAgICAgICAgICAgICAgICAgaW1wb3J0YW5jZT1UUlVFCiAgICAgICAgICAgICAgICAgICAgICAgKQoKcHJpbnQocmZfZml0X2Rvbm9yKQoKCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2fQoKdmFySW1wUGxvdChyZl9maXRfZG9ub3IsIHNvcnQgPSBUUlVFLCAKICAgICAgICAgICBuLnZhciA9IDUsCiAgICAgICAgICAgdHlwZSA9IDIsIGNsYXNzID0gTlVMTCwgc2NhbGUgPSBUUlVFLCAKICAgICAgICAgICBtYWluID0gZGVwYXJzZShzdWJzdGl0dXRlKHJmX2ZpdF9kb25vcikpKQoKCmBgYAoKYGBge3J9CgpsaWJyYXJ5KCdyYW5kb21Gb3Jlc3RFeHBsYWluZXInKQoKcGxvdF9taW5fZGVwdGhfZGlzdHJpYnV0aW9uKAogIHJmX2ZpdF9kb25vciwKICBrID0gMTAsCiAgbWluX25vX29mX3RyZWVzID0gMCwKICBtZWFuX3NhbXBsZSA9ICJ0b3BfdHJlZXMiLAogIG1lYW5fc2NhbGUgPSBGQUxTRSwKICBtZWFuX3JvdW5kID0gMiwKICBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBtaW5pbWFsIGRlcHRoIGFuZCBpdHMgbWVhbiIKKQoKYGBgCgo=
>>>>>>> f0b5b9cad967cf9811642fc02b6bcc5ada35e094